blob: e68f0139a78d32f2fd302b5e14be4eba1b5f3682 [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.impala.authorization;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.commons.lang.ArrayUtils;
import org.apache.impala.analysis.AnalysisContext;
import org.apache.impala.analysis.AnalysisContext.AnalysisResult;
import org.apache.impala.catalog.ScalarFunction;
import org.apache.impala.catalog.Type;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.common.ImpalaException;
import org.apache.impala.common.RuntimeEnv;
import org.apache.impala.service.BackendConfig;
import org.apache.impala.testutil.TestUtils;
import org.apache.impala.thrift.TDescribeOutputStyle;
import org.apache.impala.thrift.TPrivilegeLevel;
import org.apache.impala.thrift.TQueryOptions;
import org.apache.impala.thrift.TTableName;
import org.apache.sentry.api.service.thrift.TSentryRole;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* This class contains authorization tests for SQL statements.
*/
@RunWith(Parameterized.class)
public class AuthorizationStmtTest extends AuthorizationTestBase {
public static final Logger LOG = LoggerFactory.getLogger(AuthorizationStmtTest.class);
public AuthorizationStmtTest(AuthorizationProvider authzProvider)
throws ImpalaException {
super(authzProvider);
}
@BeforeClass
public static void setUp() {
RuntimeEnv.INSTANCE.setTestEnv(true);
}
@AfterClass
public static void cleanUp() {
RuntimeEnv.INSTANCE.reset();
}
@Before
public void before() throws ImpalaException {
if (authzProvider_ == AuthorizationProvider.SENTRY) {
// Remove existing roles in order to not interfere with these tests. To be able to
// list existing roles, we have to invoke listAllRoles() as the user corresponding
// to User(System.getProperty("user.name")), which has the privilege to execute
// LIST_ROLES.
User user = new User(System.getProperty("user.name"));
for (TSentryRole role : sentryService_.listAllRoles(user)) {
authzCatalog_.removeRole(role.getRoleName());
}
}
}
@Parameters
public static Collection<AuthorizationProvider> data() {
return Arrays.asList(AuthorizationProvider.SENTRY, AuthorizationProvider.RANGER);
}
private static final String[] ALLTYPES_COLUMNS_WITHOUT_ID = new String[]{"bool_col",
"tinyint_col", "smallint_col", "int_col", "bigint_col", "float_col", "double_col",
"date_string_col", "string_col", "timestamp_col", "year", "month"};
private static final String[] ALLTYPES_COLUMNS = (String[]) ArrayUtils.addAll(
new String[]{"id"}, ALLTYPES_COLUMNS_WITHOUT_ID);
@Test
public void testPrivilegeRequests() throws ImpalaException {
// Used for select *, with, and union
Set<String> expectedAuthorizables = Sets.newHashSet(
"functional.alltypes",
"functional.alltypes.id",
"functional.alltypes.bool_col",
"functional.alltypes.tinyint_col",
"functional.alltypes.smallint_col",
"functional.alltypes.int_col",
"functional.alltypes.bigint_col",
"functional.alltypes.float_col",
"functional.alltypes.double_col",
"functional.alltypes.date_string_col",
"functional.alltypes.string_col",
"functional.alltypes.timestamp_col",
"functional.alltypes.year",
"functional.alltypes.month"
);
// Select *
verifyPrivilegeReqs("select * from functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs("select alltypes.* from functional.alltypes",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "select * from alltypes",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"select alltypes.* from alltypes", expectedAuthorizables);
verifyPrivilegeReqs("select a.* from functional.alltypes a", expectedAuthorizables);
// With clause.
verifyPrivilegeReqs("with t as (select * from functional.alltypes) select * from t",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"with t as (select * from alltypes) select * from t", expectedAuthorizables);
// Union.
verifyPrivilegeReqs("select * from functional.alltypes union all " +
"select * from functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"select * from alltypes union all select * from alltypes",
expectedAuthorizables);
// Describe
expectedAuthorizables = Sets.newHashSet("functional.alltypes.*");
verifyPrivilegeReqs("describe functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "describe alltypes",
expectedAuthorizables);
// Select a specific column.
expectedAuthorizables = Sets.newHashSet(
"functional.alltypes",
"functional.alltypes.id"
);
verifyPrivilegeReqs("select id from functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs("select alltypes.id from functional.alltypes",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"select alltypes.id from alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"select id from alltypes", expectedAuthorizables);
verifyPrivilegeReqs("select alltypes.id from functional.alltypes",
expectedAuthorizables);
verifyPrivilegeReqs("select a.id from functional.alltypes a", expectedAuthorizables);
// Insert.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("insert into functional.alltypes(id) partition(month, year) " +
"values(1, 1, 2018)", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"insert into alltypes(id) partition(month, year) values(1, 1, 2018)",
expectedAuthorizables);
// Insert with constant select.
expectedAuthorizables = Sets.newHashSet("functional.zipcode_incomes");
verifyPrivilegeReqs("insert into functional.zipcode_incomes(id) select '123'",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"insert into zipcode_incomes(id) select '123'", expectedAuthorizables);
// Truncate.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("truncate table functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"truncate table alltypes", expectedAuthorizables);
// Load
expectedAuthorizables = Sets.newHashSet(
"functional.alltypes",
"hdfs://localhost:20500/test-warehouse/tpch.lineitem"
);
verifyPrivilegeReqs("load data inpath " +
"'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " +
"into table functional.alltypes partition(month=10, year=2009)",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "load data inpath " +
"'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " +
"into table alltypes partition(month=10, year=2009)",
expectedAuthorizables);
// Reset metadata.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("invalidate metadata functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"invalidate metadata alltypes", expectedAuthorizables);
verifyPrivilegeReqs("refresh functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "refresh alltypes",
expectedAuthorizables);
// Show tables.
expectedAuthorizables = Sets.newHashSet("functional.*.*");
verifyPrivilegeReqs("show tables in functional", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "show tables",
expectedAuthorizables);
// Show partitions.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("show partitions functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"show partitions alltypes", expectedAuthorizables);
// Show range partitions.
expectedAuthorizables = Sets.newHashSet("functional_kudu.dimtbl");
verifyPrivilegeReqs("show range partitions functional_kudu.dimtbl",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"),
"show range partitions dimtbl", expectedAuthorizables);
// Show table stats.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("show table stats functional.alltypes",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"show table stats alltypes", expectedAuthorizables);
// Show column stats.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("show column stats functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"show column stats alltypes", expectedAuthorizables);
// Show create table.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("show create table functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"show create table functional.alltypes", expectedAuthorizables);
// Show create view.
expectedAuthorizables = Sets.newHashSet("functional.alltypes_view");
verifyPrivilegeReqs("show create view functional.alltypes_view",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"show create view functional.alltypes_view", expectedAuthorizables);
// Compute stats.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("compute stats functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "compute stats alltypes",
expectedAuthorizables);
// Drop stats.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("drop stats functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "drop stats alltypes",
expectedAuthorizables);
// Create table.
expectedAuthorizables = Sets.newHashSet("functional.new_table");
verifyPrivilegeReqs("create table functional.new_table(i int)",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"create table new_table(i int)", expectedAuthorizables);
// Create view.
expectedAuthorizables = Sets.newHashSet("functional.new_view");
verifyPrivilegeReqs("create view functional.new_view as select 1",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"create view new_view as select 1", expectedAuthorizables);
// Drop table.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("drop table functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "drop table alltypes",
expectedAuthorizables);
// Drop view.
expectedAuthorizables = Sets.newHashSet("functional.alltypes_view");
verifyPrivilegeReqs("drop view functional.alltypes_view", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"drop view alltypes_view",
expectedAuthorizables);
// Update table.
expectedAuthorizables = Sets.newHashSet(
"functional_kudu.alltypes",
"functional_kudu.alltypes.id",
"functional_kudu.alltypes.int_col");
verifyPrivilegeReqs("update functional_kudu.alltypes set int_col = 1",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"),
"update alltypes set int_col = 1", expectedAuthorizables);
// Upsert table.
expectedAuthorizables = Sets.newHashSet("functional_kudu.alltypes");
verifyPrivilegeReqs("upsert into table functional_kudu.alltypes(id, int_col) " +
"values(1, 1)", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"),
"upsert into table alltypes(id, int_col) values(1, 1)", expectedAuthorizables);
// Delete table.
expectedAuthorizables = Sets.newHashSet(
"functional_kudu.alltypes",
"functional_kudu.alltypes.id");
verifyPrivilegeReqs("delete from functional_kudu.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"),
"delete from alltypes",
expectedAuthorizables);
// Alter table.
expectedAuthorizables = Sets.newHashSet("functional.alltypes");
verifyPrivilegeReqs("alter table functional.alltypes add columns(c1 int)",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"alter table alltypes add columns(c1 int)", expectedAuthorizables);
// Alter view.
expectedAuthorizables = Sets.newHashSet("functional.alltypes_view");
verifyPrivilegeReqs("alter view functional.alltypes_view as select 1",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"alter view alltypes_view as select 1", expectedAuthorizables);
}
@Test
public void testCopyTestCasePrivileges() throws ImpalaException {
// Used for select *, with, and union
Set<String> expectedAuthorizables = Sets.newHashSet(
"functional", // For including the DB related metadata in the testcase file.
"functional.alltypes",
"functional.alltypes.id",
"functional.alltypes.bool_col",
"functional.alltypes.tinyint_col",
"functional.alltypes.smallint_col",
"functional.alltypes.int_col",
"functional.alltypes.bigint_col",
"functional.alltypes.float_col",
"functional.alltypes.double_col",
"functional.alltypes.date_string_col",
"functional.alltypes.string_col",
"functional.alltypes.timestamp_col",
"functional.alltypes.year",
"functional.alltypes.month",
"hdfs://localhost:20500/tmp" // For the testcase output URI
);
// Select *
verifyPrivilegeReqs("copy testcase to '/tmp' select * from functional" +
".alltypes", expectedAuthorizables);
verifyPrivilegeReqs("copy testcase to '/tmp' select alltypes.* from " +
"functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "copy testcase to " +
"'/tmp' select * from alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"copy testcase to '/tmp' select alltypes.* from alltypes",
expectedAuthorizables);
verifyPrivilegeReqs("copy testcase to '/tmp' select a.* from functional" +
".alltypes a", expectedAuthorizables);
// With clause.
verifyPrivilegeReqs("copy testcase to '/tmp' with t as (select * from " +
"functional.alltypes) select * from t", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"copy testcase to '/tmp' with t as (select * from alltypes) select * " +
"from t", expectedAuthorizables);
// Union.
verifyPrivilegeReqs("copy testcase to '/tmp' select * from functional" +
".alltypes union all select * from functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "copy testcase to '/tmp'"
+ "select * from alltypes union all select * from" + " alltypes",
expectedAuthorizables);
// Select a specific column.
expectedAuthorizables = Sets.newHashSet(
"functional",
"functional.alltypes",
"functional.alltypes.id",
"hdfs://localhost:20500/tmp"
);
verifyPrivilegeReqs("copy testcase to '/tmp' select id from " +
"functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs("copy testcase to '/tmp' select alltypes.id from " +
"functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"),
"copy testcase to '/tmp' select alltypes.id from alltypes",
expectedAuthorizables);
verifyPrivilegeReqs(createAnalysisCtx("functional"), "copy testcase to " +
"'/tmp' select id from alltypes", expectedAuthorizables);
verifyPrivilegeReqs("copy testcase to '/tmp' select alltypes.id from " +
"functional.alltypes", expectedAuthorizables);
verifyPrivilegeReqs("copy testcase to '/tmp' select a.id from functional" +
".alltypes a", expectedAuthorizables);
// Verify VIEW_METADATA privileges on authorizables.
final String copyTestCasePrefix = "copy testcase to '/tmp' ";
for (AuthzTest authzTest: new AuthzTest[] {
authorize(copyTestCasePrefix + "with t as (select id from functional.alltypes) " +
"select * from t"),
authorize(copyTestCasePrefix + "select id from functional.alltypes")}) {
authzTest
// Ideal case, when all the privileges are in place.
.ok(onUri(false, "/tmp", TPrivilegeLevel.ALL),
onDatabase("functional", viewMetadataPrivileges()),
onTable("functional", "alltypes", viewMetadataPrivileges()))
// DB does not have the metadata access privileges
.error(accessError("functional"),
onUri(false, "/tmp", TPrivilegeLevel.ALL),
onDatabase("functional", allExcept(viewMetadataPrivileges())),
onTable("functional", "alltypes", viewMetadataPrivileges()))
// URI does not have ALL privilege.
.error(accessError("hdfs://localhost:20500/tmp"),
onDatabase("functional", viewMetadataPrivileges()),
onTable("functional", "alltypes", viewMetadataPrivileges()));
}
}
@Test
public void testSelect() throws ImpalaException {
for (AuthzTest authzTest: new AuthzTest[]{
// Select a specific column on a table.
authorize("select id from functional.alltypes"),
// With clause with select.
authorize("with t as (select id from functional.alltypes) select * from t")}) {
authzTest
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "alltypes", "id", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onTable("functional",
"alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
}
// Select without referencing a column.
authorize("select 1 from functional.alltypes")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
// Select a specific column on a view.
for (AuthzTest test: new AuthzTest[]{
authorize("select id from functional.alltypes_view"),
authorize("select 2 * v.id from functional.alltypes_view v"),
authorize("select cast(id as bigint) from functional.alltypes_view")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "alltypes_view", "id", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes_view"))
.error(selectError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes_view"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
}
// Constant select.
authorize("select 1").ok();
// Select on view and join table.
authorize("select a.id from functional.view_view a " +
"join functional.alltypesagg b ON (a.id = b.id)")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "view_view", TPrivilegeLevel.ALL),
onTable("functional", "alltypesagg", TPrivilegeLevel.ALL))
.ok(onTable("functional", "view_view", TPrivilegeLevel.OWNER),
onTable("functional", "alltypesagg", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "view_view", TPrivilegeLevel.ALL),
onTable("functional", "alltypesagg", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "view_view", TPrivilegeLevel.OWNER),
onTable("functional", "alltypesagg", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "view_view", TPrivilegeLevel.SELECT),
onTable("functional", "alltypesagg", TPrivilegeLevel.ALL))
.ok(onTable("functional", "view_view", TPrivilegeLevel.SELECT),
onTable("functional", "alltypesagg", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "view_view", TPrivilegeLevel.SELECT),
onTable("functional", "alltypesagg", TPrivilegeLevel.SELECT))
.error(selectError("functional.view_view"))
.error(selectError("functional.view_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.view_view"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.view_view"), onTable("functional", "view_view",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)), onTable("functional", "alltypesagg",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
// Tests authorization after a statement has been rewritten (IMPALA-3915).
authorize("select * from functional_seq_snap.subquery_view")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional_seq_snap", TPrivilegeLevel.ALL))
.ok(onDatabase("functional_seq_snap", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional_seq_snap", TPrivilegeLevel.SELECT))
.ok(onTable("functional_seq_snap", "subquery_view", TPrivilegeLevel.ALL))
.ok(onTable("functional_seq_snap", "subquery_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional_seq_snap", "subquery_view", TPrivilegeLevel.SELECT))
.error(selectError("functional_seq_snap.subquery_view"))
.error(selectError("functional_seq_snap.subquery_view"), onServer(
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional_seq_snap.subquery_view"),
onDatabase("functional_seq_snap", allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional_seq_snap.subquery_view"),
onTable("functional_seq_snap", "subquery_view", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)));
// Select a UDF.
ScalarFunction fn = addFunction("functional", "f");
try {
authorize("select functional.f()")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(viewMetadataPrivileges()))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", viewMetadataPrivileges()))
.error(accessError("functional"))
.error(accessError("functional"), onServer(allExcept(
viewMetadataPrivileges())))
.error(accessError("functional"), onDatabase("functional", allExcept(
viewMetadataPrivileges())));
} finally {
removeFunction(fn);
}
// Select from non-existent database.
authorize("select 1 from nodb.alltypes")
.error(selectError("nodb.alltypes"));
// Select from non-existent table.
authorize("select 1 from functional.notbl")
.error(selectError("functional.notbl"));
// Select with inline view.
authorize("select a.* from (select * from functional.alltypes) a")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "alltypes", ALLTYPES_COLUMNS, TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
// Select with columns referenced in function, where clause and group by.
authorize("select count(id), int_col from functional.alltypes where id = 10 " +
"group by id, int_col")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "alltypes", new String[]{"id", "int_col"},
TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
// Select on tables with complex types.
authorize("select a.int_struct_col.f1 from functional.allcomplextypes a " +
"where a.id = 1")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "allcomplextypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "allcomplextypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "allcomplextypes", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "allcomplextypes",
new String[]{"id", "int_struct_col"}, TPrivilegeLevel.SELECT))
.error(selectError("functional.allcomplextypes"))
.error(selectError("functional.allcomplextypes"), onServer(
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.allcomplextypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.allcomplextypes"), onTable("functional",
"allcomplextypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
authorize("select key, pos, item.f1, f2 from functional.allcomplextypes t, " +
"t.struct_array_col, functional.allcomplextypes.int_map_col")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "allcomplextypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "allcomplextypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "allcomplextypes", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "allcomplextypes",
new String[]{"struct_array_col", "int_map_col"}, TPrivilegeLevel.SELECT))
.error(selectError("functional.allcomplextypes"))
.error(selectError("functional.allcomplextypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.allcomplextypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.allcomplextypes"), onTable("functional",
"allcomplextypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
for (AuthzTest authzTest: new AuthzTest[]{
// Select with cross join.
authorize("select * from functional.alltypes union all " +
"select * from functional.alltypessmall"),
// Union on tables.
authorize("select * from functional.alltypes a cross join " +
"functional.alltypessmall b")}) {
authzTest.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL),
onTable("functional", "alltypessmall", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER),
onTable("functional", "alltypessmall", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.SELECT),
onTable("functional", "alltypessmall", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.SELECT),
onTable("functional", "alltypessmall", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL),
onTable("functional", "alltypessmall", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER),
onTable("functional", "alltypessmall", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.SELECT),
onTable("functional", "alltypessmall", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "alltypes", ALLTYPES_COLUMNS,
TPrivilegeLevel.SELECT), onColumn("functional", "alltypessmall",
ALLTYPES_COLUMNS, TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)), onTable("functional", "alltypessmall",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypessmall"), onColumn("functional",
"alltypes", ALLTYPES_COLUMNS, TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"), onColumn("functional",
"alltypessmall", ALLTYPES_COLUMNS, TPrivilegeLevel.SELECT));
}
// Union on views.
authorize("select id from functional.alltypes_view union all " +
"select x from functional.alltypes_view_sub")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL),
onTable("functional", "alltypes_view_sub", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER),
onTable("functional", "alltypes_view_sub", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT),
onTable("functional", "alltypes_view_sub", TPrivilegeLevel.SELECT))
.ok(onColumn("functional", "alltypes_view", "id", TPrivilegeLevel.SELECT),
onColumn("functional", "alltypes_view_sub", "x", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes_view"))
.error(selectError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes_view"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)),
onTable("functional", "alltypes_view_sub", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes_view_sub"), onTable("functional",
"alltypes_view_sub", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)),
onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT));
// Union from non-existent databases.
authorize("select id from nodb.alltypes union all " +
"select id from functional.alltypesagg").error(selectError("nodb.alltypes"));
// Union from non-existent tables.
authorize("select id from functional.notbl union all " +
"select id from functional.alltypesagg").error(selectError("functional.notbl"));
}
@Test
public void testInsert() throws ImpalaException {
// Basic insert into a table.
for (AuthzTest test: new AuthzTest[]{
authorize("insert into functional.zipcode_incomes(id) values('123')"),
// Explain insert.
authorize("explain insert into functional.zipcode_incomes(id) values('123')")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.INSERT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT))
.ok(onTable("functional", "zipcode_incomes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "zipcode_incomes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "zipcode_incomes", TPrivilegeLevel.INSERT))
.error(insertError("functional.zipcode_incomes"))
.error(insertError("functional.zipcode_incomes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT)))
.error(insertError("functional.zipcode_incomes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.INSERT)))
.error(insertError("functional.zipcode_incomes"), onTable("functional",
"zipcode_incomes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.INSERT)));
}
for (AuthzTest test: new AuthzTest[]{
// With clause with insert.
authorize("with t as (select * from functional.alltypestiny) " +
"insert into functional.alltypes partition(month, year) " +
"select * from t"),
// Insert with select on a target table.
authorize("insert into functional.alltypes partition(month, year) " +
"select * from functional.alltypestiny where id < 100")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL),
onTable("functional", "alltypestiny", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER),
onTable("functional", "alltypestiny", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onTable("functional", "alltypestiny", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onColumn("functional", "alltypestiny", ALLTYPES_COLUMNS,
TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypestiny"))
.error(selectError("functional.alltypestiny"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypestiny"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)))
.error(insertError("functional.alltypes"), onTable("functional",
"alltypestiny", TPrivilegeLevel.SELECT), onTable("functional",
"alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.INSERT)))
.error(selectError("functional.alltypestiny"), onTable("functional",
"alltypestiny", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)), onTable("functional", "alltypes",
TPrivilegeLevel.INSERT));
}
// Insert with select on a target view.
authorize("insert into functional.alltypes partition(month, year) " +
"select * from functional.alltypes_view where id < 100")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL),
onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER),
onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onColumn("functional", "alltypes_view", ALLTYPES_COLUMNS,
TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes_view"))
.error(selectError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes_view"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT)))
.error(insertError("functional.alltypes"), onTable("functional",
"alltypes_view", TPrivilegeLevel.SELECT), onTable("functional",
"alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.INSERT)))
.error(selectError("functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)),
onTable("functional", "alltypes", TPrivilegeLevel.INSERT));
// Insert with inline view.
authorize("insert into functional.alltypes partition(month, year) " +
"select b.* from functional.alltypesagg a join (select * from " +
"functional.alltypestiny) b on (a.int_col = b.int_col)")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL),
onTable("functional", "alltypesagg", TPrivilegeLevel.ALL),
onTable("functional", "alltypestiny", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER),
onTable("functional", "alltypesagg", TPrivilegeLevel.OWNER),
onTable("functional", "alltypestiny", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onTable("functional", "alltypesagg", TPrivilegeLevel.SELECT),
onTable("functional", "alltypestiny", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypesagg"))
.error(selectError("functional.alltypesagg"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypesagg"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT)))
.error(insertError("functional.alltypes"), onTable("functional",
"alltypesagg", TPrivilegeLevel.SELECT), onTable("functional",
"alltypestiny", TPrivilegeLevel.SELECT), onTable("functional",
"alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.INSERT)))
.error(selectError("functional.alltypesagg"), onTable("functional",
"alltypesagg", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)),
onTable("functional", "alltypestiny", TPrivilegeLevel.SELECT),
onTable("functional", "alltypes", TPrivilegeLevel.INSERT))
.error(selectError("functional.alltypestiny"), onTable("functional",
"alltypesagg", TPrivilegeLevel.SELECT), onTable("functional",
"alltypestiny", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)),
onTable("functional", "alltypes", TPrivilegeLevel.INSERT));
// Inserting into a view is not allowed.
authorize("insert into functional.alltypes_view(id) values(123)")
.error(insertError("functional.alltypes_view"));
// Inserting into a non-existent database.
authorize("insert into nodb.alltypes(id) values(1)")
.error(insertError("nodb.alltypes"));
// Inserting into a non-existent table.
authorize("insert into functional.notbl(id) values(1)")
.error(insertError("functional.notbl"));
}
@Test
public void testUseDb() throws ImpalaException {
AuthzTest test = authorize("use functional");
for (TPrivilegeLevel privilege: TPrivilegeLevel.values()) {
test.ok(onServer(privilege))
.ok(onDatabase("functional", privilege))
.ok(onTable("functional", "alltypes", privilege))
.ok(onColumn("functional", "alltypes", "id", privilege));
}
test.error(accessError("functional.*.*"));
// Accessing default database should always be allowed.
authorize("use default").ok();
// Accessing system database should always be allowed.
authorize("use _impala_builtins").ok();
// Use a non-existent database.
authorize("use nodb").error(accessError("nodb.*.*"));
}
@Test
public void testTruncate() throws ImpalaException {
// Truncate a table
authorize("truncate table functional.alltypes")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.INSERT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT))
.error(insertError("functional.alltypes"))
.error(insertError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT)))
.error(insertError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT)))
.error(insertError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.INSERT)));
// Truncate a non-existent database.
authorize("truncate table nodb.alltypes")
.error(insertError("nodb.alltypes"));
// Truncate a non-existent table.
authorize("truncate table functional.notbl")
.error(insertError("functional.notbl"));
// Truncating a view is not supported.
authorize("truncate table functional.alltypes_view")
.error(insertError("functional.alltypes_view"));
}
@Test
public void testLoad() throws ImpalaException {
// Load into a table.
authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " +
"into table functional.alltypes partition(month=10, year=2009)")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.OWNER))
.error(insertError("functional.alltypes"))
.error(accessError("hdfs://localhost:20500/test-warehouse/tpch.lineitem"),
onDatabase("functional", TPrivilegeLevel.INSERT))
.error(accessError("hdfs://localhost:20500/test-warehouse/tpch.lineitem"),
onTable("functional", "alltypes", TPrivilegeLevel.INSERT))
.error(insertError("functional.alltypes"),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.ALL))
.error(insertError("functional.alltypes"),
onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem",
TPrivilegeLevel.OWNER));
// Load from non-existent URI.
authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/nouri' " +
"into table functional.alltypes partition(month=10, year=2009)")
.error(insertError("functional.alltypes"))
.error(accessError("hdfs://localhost:20500/test-warehouse/nouri"),
onDatabase("functional", TPrivilegeLevel.INSERT))
.error(accessError("hdfs://localhost:20500/test-warehouse/nouri"),
onTable("functional", "alltypes", TPrivilegeLevel.INSERT));
// Load into non-existent database.
authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " +
"into table nodb.alltypes partition(month=10, year=2009)")
.error(insertError("nodb.alltypes"))
.error(insertError("nodb.alltypes"), onUri(
"hdfs://localhost:20500/test-warehouse/tpch.nouri", TPrivilegeLevel.ALL))
.error(insertError("nodb.alltypes"), onUri(
"hdfs://localhost:20500/test-warehouse/tpch.nouri", TPrivilegeLevel.OWNER));
// Load into non-existent table.
authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " +
"into table functional.notbl partition(month=10, year=2009)")
.error(insertError("functional.notbl"))
.error(insertError("functional.notbl"), onUri(
"hdfs://localhost:20500/test-warehouse/tpch.nouri", TPrivilegeLevel.ALL))
.error(insertError("functional.notbl"), onUri(
"hdfs://localhost:20500/test-warehouse/tpch.nouri", TPrivilegeLevel.OWNER));
// Load into a view is not supported.
authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " +
"into table functional.alltypes_view")
.error(insertError("functional.alltypes_view"));
}
@Test
public void testResetMetadata() throws ImpalaException {
// Invalidate metadata/refresh authorization on server.
for (AuthzTest test: new AuthzTest[]{
authorize("invalidate metadata"),
authorize("refresh authorization")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.REFRESH))
.error(refreshError("server"));
}
// Invalidate metadata/refresh on a table / view
for(String name: new String[] {"alltypes", "alltypes_view"}) {
for (AuthzTest test: new AuthzTest[]{
authorize("invalidate metadata functional." + name),
authorize("refresh functional." + name)}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.REFRESH))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.REFRESH))
.ok(onTable("functional", name, TPrivilegeLevel.ALL))
.ok(onTable("functional", name, TPrivilegeLevel.OWNER))
.ok(onTable("functional", name, TPrivilegeLevel.REFRESH))
.error(refreshError("functional." + name))
.error(refreshError("functional." + name), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.REFRESH)))
.error(refreshError("functional." + name), onTable("functional", name,
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.REFRESH)));
}
}
authorize("refresh functions functional")
.ok(onServer(TPrivilegeLevel.REFRESH))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.REFRESH))
.error(refreshError("functional"))
.error(refreshError("functional"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.REFRESH)))
.error(refreshError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.REFRESH)));
// Reset metadata in non-existent database.
authorize("invalidate metadata nodb").error(refreshError("default.nodb"));
authorize("refresh nodb").error(refreshError("default.nodb"));
authorize("refresh functions nodb").error(refreshError("nodb"));
}
@Test
public void testShow() throws ImpalaException {
// Show databases should always be allowed.
authorize("show databases").ok();
// Show tables.
AuthzTest test = authorize("show tables in functional");
for (TPrivilegeLevel privilege: TPrivilegeLevel.values()) {
test.ok(onServer(privilege))
.ok(onDatabase("functional", privilege))
.ok(onTable("functional", "alltypes", privilege));
}
test.error(accessError("functional.*.*"));
// Show functions.
test = authorize("show functions in functional");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
test.ok(onServer(privilege))
.ok(onDatabase("functional", privilege));
}
test.error(accessError("functional"));
// Show tables in system database should always be allowed.
authorize("show tables in _impala_builtins").ok();
// Show tables for non-existent database.
authorize("show tables in nodb").error(accessError("nodb"));
// Show partitions, table stats, and column stats
for (AuthzTest authzTest: new AuthzTest[]{
authorize("show partitions functional.alltypes"),
authorize("show table stats functional.alltypes"),
authorize("show column stats functional.alltypes")}) {
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest.ok(onServer(privilege))
.ok(onDatabase("functional", privilege))
.ok(onTable("functional", "alltypes", privilege))
.error(accessError("functional.alltypes"), onColumn("functional", "alltypes",
"id", TPrivilegeLevel.SELECT));
}
authzTest.error(accessError("functional"));
}
// Show range partitions.dimtbl
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authorize("show range partitions functional_kudu.dimtbl")
.ok(onServer(privilege))
.ok(onDatabase("functional_kudu", privilege))
.ok(onTable("functional_kudu", "dimtbl", privilege))
.error(accessError("functional_kudu.dimtbl"), onColumn("functional_kudu",
"dimtbl", "id", TPrivilegeLevel.SELECT))
.error(accessError("functional_kudu"));
}
// Show files.
for (AuthzTest authzTest: new AuthzTest[]{
authorize("show files in functional.alltypes"),
authorize("show files in functional.alltypes partition(month=10, year=2010)")}) {
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest.ok(onServer(privilege))
.ok(onDatabase("functional", privilege))
.ok(onTable("functional", "alltypes", privilege));
}
authzTest.error(accessError("functional"));
}
// Show current roles should always be allowed.
authorize("show current roles").ok();
// Show roles should always be allowed.
authorize("show roles").ok();
// Show role grant group should always be allowed.
authorize(String.format("show role grant group `%s`", user_.getName())).ok();
// Show grant role/user should always be allowed.
try {
authzCatalog_.addRole("test_role");
authzCatalog_.addUser("test_user");
for (String type : new String[]{"role test_role", "user test_user"}) {
authorize(String.format("show grant %s", type)).ok();
authorize(String.format("show grant %s on server", type)).ok();
authorize(String.format("show grant %s on database functional", type)).ok();
authorize(String.format("show grant %s on table functional.alltypes", type)).ok();
authorize(String.format("show grant %s on uri '/test-warehouse'", type)).ok();
}
} finally {
authzCatalog_.removeRole("test_role");
authzCatalog_.removeUser("test_user");
}
// Show create table.
test = authorize("show create table functional.alltypes");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
test.ok(onServer(privilege))
.ok(onDatabase("functional", privilege))
.ok(onTable("functional", "alltypes", privilege));
}
test.error(accessError("functional"));
// Show create table on non-existent database.
authorize("show create table nodb.alltypes").error(accessError("nodb.alltypes"));
// Show create table on non-existent table.
authorize("show create table functional.notbl")
.error(accessError("functional.notbl"));
// Show create view.
test = authorize("show create view functional.alltypes_view");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
test.ok(onServer(privilege, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", privilege, TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes_view", privilege),
onTable("functional", "alltypes", TPrivilegeLevel.SELECT));
}
test.error(accessError("functional"));
// Show create view on non-existent database.
authorize("show create view nodb.alltypes").error(accessError("nodb.alltypes"));
// Show create view on non-existent table.
authorize("show create view functional.notbl").error(accessError("functional.notbl"));
// IMPALA-7325: show create view that references built-in function(s) should not
// require access to the _impala_builtins database this is because reading metadata
// in system database should always be allowed.
addTestView(authzCatalog_, "create view functional.test_view as " +
"select count(*) from functional.alltypes");
test = authorize("show create view functional.test_view");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
test.ok(onServer(privilege, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", privilege, TPrivilegeLevel.SELECT))
.ok(onTable("functional", "test_view", privilege),
onTable("functional", "alltypes", privilege, TPrivilegeLevel.SELECT));
}
test.error(accessError("functional.test_view"))
.error(accessError("functional.test_view"), onServer(
allExcept(viewMetadataPrivileges())))
.error(accessError("functional.test_view"), onDatabase("functional",
allExcept(viewMetadataPrivileges())))
.error(accessError("functional.test_view"), onTable("functional", "test_view",
allExcept(viewMetadataPrivileges())), onTable("functional", "alltypes",
TPrivilegeLevel.SELECT))
.error(viewDefError("functional.test_view"), onTable("functional", "test_view",
TPrivilegeLevel.SELECT), onTable("functional", "alltypes", allExcept(
viewMetadataPrivileges())));
// Show create function.
ScalarFunction fn = addFunction("functional", "f");
try {
test = authorize("show create function functional.f");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
test.ok(onServer(privilege))
.ok(onDatabase("functional", privilege));
}
test.error(accessError("functional"));
// Show create function on non-existent database.
authorize("show create function nodb.f").error(accessError("nodb"));
// Show create function on non-existent function.
authorize("show create function functional.nofn").error(accessError("functional"));
} finally {
removeFunction(fn);
}
// Show create function in system database should always be allowed.
authorize("show create function _impala_builtins.pi").ok();
// Show data sources should always be allowed.
authorize("show data sources").ok();
}
/**
* Test describe output of Databases and tables.
* From https://issues.apache.org/jira/browse/IMPALA-6479
* Column level select privileges should limit output.
*/
@Test
public void testDescribe() throws ImpalaException {
// Describe database.
AuthzTest authzTest = authorize("describe database functional");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest.ok(onServer(privilege))
.ok(onDatabase("functional", privilege));
}
authzTest.error(accessError("functional"))
.error(accessError("functional"), onServer(allExcept(viewMetadataPrivileges())))
.error(accessError("functional"), onDatabase("functional",
allExcept(viewMetadataPrivileges())));
// Describe on non-existent database.
authorize("describe database nodb").error(accessError("nodb"));
// Describe table.
TTableName tableName = new TTableName("functional", "alltypes");
TDescribeOutputStyle style = TDescribeOutputStyle.MINIMAL;
authzTest = authorize("describe functional.alltypes");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest
.okDescribe(tableName, describeOutput(style).includeStrings(ALLTYPES_COLUMNS),
onServer(privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(ALLTYPES_COLUMNS),
onDatabase("functional", privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(ALLTYPES_COLUMNS),
onTable("functional", "alltypes", privilege));
}
authzTest
// In this test, since we only have column level privileges on "id", then
// only the "id" column should show and the others should not.
.okDescribe(tableName, describeOutput(style).includeStrings(new String[]{"id"})
.excludeStrings(ALLTYPES_COLUMNS_WITHOUT_ID), onColumn("functional",
"alltypes", "id", TPrivilegeLevel.SELECT))
// If there exists a privilege in the given table/column with incorrect
// privilege type, we return an empty result instead of an error.
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onServer(allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onDatabase("functional", allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onTable("functional", "alltypes", allExcept(viewMetadataPrivileges())))
.error(accessError("functional.alltypes"));
// Describe table extended.
tableName = new TTableName("functional", "alltypes");
style = TDescribeOutputStyle.EXTENDED;
String[] checkStrings = (String[]) ArrayUtils.addAll(ALLTYPES_COLUMNS,
new String[]{"Location:"});
authzTest = authorize("describe functional.alltypes");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest
.okDescribe(tableName, describeOutput(style).includeStrings(checkStrings),
onServer(privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(checkStrings),
onDatabase("functional", privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(checkStrings),
onTable("functional", "alltypes", privilege));
}
authzTest
// Location should not appear with only column level auth.
.okDescribe(tableName, describeOutput(style).includeStrings(new String[]{"id"})
.excludeStrings((String[]) ArrayUtils.addAll(ALLTYPES_COLUMNS_WITHOUT_ID,
new String[]{"Location:"})), onColumn("functional", "alltypes", "id",
TPrivilegeLevel.SELECT))
// If there exists a privilege in the given table/column with incorrect
// privilege type, we return an empty result instead of an error.
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onServer(allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onDatabase("functional", allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onTable("functional", "alltypes", allExcept(viewMetadataPrivileges())))
.error(accessError("functional.alltypes"));
// Describe view.
tableName = new TTableName("functional", "alltypes_view");
style = TDescribeOutputStyle.MINIMAL;
authzTest = authorize("describe functional.alltypes_view");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest
.okDescribe(tableName, describeOutput(style).includeStrings(ALLTYPES_COLUMNS),
onServer(privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(ALLTYPES_COLUMNS),
onDatabase("functional", privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(ALLTYPES_COLUMNS),
onTable("functional", "alltypes_view", privilege));
}
authzTest
// If there exists a privilege in the given table/column with incorrect
// privilege type, we return an empty result instead of an error.
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onServer(allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onDatabase("functional", allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onTable("functional", "alltypes_view", allExcept(viewMetadataPrivileges())))
.error(accessError("functional.alltypes_view"));
// Describe view extended.
tableName = new TTableName("functional", "alltypes_view");
style = TDescribeOutputStyle.EXTENDED;
// Views have extra output to explicitly check
String[] viewStrings = new String[]{"View Original Text:", "View Expanded Text:"};
checkStrings = (String[]) ArrayUtils.addAll(ALLTYPES_COLUMNS, viewStrings);
authzTest = authorize("describe functional.alltypes_view");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest
.okDescribe(tableName, describeOutput(style).includeStrings(checkStrings),
onServer(privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(checkStrings),
onDatabase("functional", privilege))
.okDescribe(tableName, describeOutput(style).includeStrings(checkStrings),
onTable("functional", "alltypes_view", privilege));
}
authzTest
// If there exists a privilege in the given table/column with incorrect
// privilege type, we return an empty result instead of an error.
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onServer(allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onDatabase("functional", allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, describeOutput(style).excludeStrings(ALLTYPES_COLUMNS),
onTable("functional", "alltypes_view", allExcept(viewMetadataPrivileges())))
.error(accessError("functional.alltypes_view"));
// Describe specific column on a table.
authzTest = authorize("describe functional.allcomplextypes.int_struct_col");
for (TPrivilegeLevel privilege: viewMetadataPrivileges()) {
authzTest.ok(onServer(privilege))
.ok(onDatabase("functional", privilege))
.ok(onTable("functional", "allcomplextypes", privilege));
}
authzTest.ok(onColumn("functional", "allcomplextypes", "int_struct_col",
TPrivilegeLevel.SELECT))
.error(accessError("functional.allcomplextypes"));
for (AuthzTest test : new AuthzTest[]{
// User has access to a different column.
authorize("describe functional.allcomplextypes.int_struct_col"),
// Insufficient privileges on complex type column, accessing member
authorize("describe functional.allcomplextypes.complex_struct_col.f2"),
// Insufficient privileges on non-complex type column, accessing member
authorize("describe functional.allcomplextypes.nested_struct_col.f1")}) {
test.error(accessError("functional.allcomplextypes"), onColumn("functional",
"allcomplextypes", "id", TPrivilegeLevel.SELECT));
}
}
@Test
public void testStats() throws ImpalaException {
// Compute stats.
authorize("compute stats functional.alltypes")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER, TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT))
.error(alterError("functional.alltypes"))
.error(alterError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)))
.error(alterError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)))
.error(alterError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)));
// Compute stats on database that does not exist.
authorize("compute stats nodb.notbl")
.error(alterError("nodb.notbl"))
.error(alterError("nodb.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)))
.error(alterError("nodb.notbl"), onDatabase("nodb", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)));
// Compute stats on table that does not exist.
authorize("compute stats functional.notbl")
.error(alterError("functional.notbl"))
.error(alterError("functional.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)))
.error(alterError("functional.notbl"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)));
// Drop stats.
authorize("drop stats functional.alltypes")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes"))
.error(alterError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
// Drop stats on database that does not exist.
authorize("drop stats nodb.notbl")
.error(alterError("nodb.notbl"))
.error(alterError("nodb.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("nodb.notbl"), onDatabase("nodb", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
// Drop stats on table that does not exist.
authorize("drop stats functional.notbl")
.error(alterError("functional.notbl"))
.error(alterError("functional.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.notbl"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
}
@Test
public void testCreateDatabase() throws ImpalaException {
for (AuthzTest test: new AuthzTest[]{
authorize("create database newdb"),
authorize("create database if not exists newdb")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE))
.error(createError("newdb"))
.error(createError("newdb"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
}
// Create a database with a specific location.
String uri = "hdfs://localhost:20500/test-warehouse/new_location";
String stmt = "create database newdb location " + "'" + uri + "'";
authorize(stmt)
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE), onUri(uri, TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.CREATE), onUri(uri, TPrivilegeLevel.OWNER))
.error(createError("newdb"))
.error(createError("newdb"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)),
onUri(uri, TPrivilegeLevel.ALL))
.error(createError("newdb"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)),
onUri(uri, TPrivilegeLevel.OWNER))
.error(accessError(uri), onServer(TPrivilegeLevel.CREATE));
// Database already exists.
for (AuthzTest test: new AuthzTest[]{
authorize("create database functional"),
authorize("create database if not exists functional")}) {
test.error(createError("functional"))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
}
authorize("create database if not exists _impala_builtins")
.error(systemDbError(), onServer(TPrivilegeLevel.ALL))
.error(systemDbError(), onServer(TPrivilegeLevel.OWNER));
}
@Test
public void testCreateTable() throws ImpalaException {
for (AuthzTest test: new AuthzTest[]{
authorize("create table functional.new_table(i int)"),
authorize("create external table functional.new_table(i int)")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
}
// Create table like.
authorize("create table functional.new_table like functional.alltypes")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(join(viewMetadataPrivileges(), TPrivilegeLevel.CREATE)))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", join(viewMetadataPrivileges(),
TPrivilegeLevel.CREATE)))
.ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE),
onTable("functional", "alltypes", viewMetadataPrivileges()))
.error(accessError("functional.alltypes"))
.error(accessError("functional.alltypes"), onServer(allExcept(
join(viewMetadataPrivileges(), TPrivilegeLevel.CREATE))))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.SELECT)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onTable(
"functional", "alltypes", viewMetadataPrivileges()))
.error(accessError("functional.alltypes"), onDatabase("functional",
TPrivilegeLevel.CREATE), onTable("functional", "alltypes", allExcept(
viewMetadataPrivileges())));
// Table already exists.
for (AuthzTest test : new AuthzTest[]{
authorize("create table functional.alltypes(i int)"),
authorize("create table if not exists functional.alltypes(i int)")}) {
test.error(createError("functional"))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
}
// CTAS.
for (AuthzTest test: new AuthzTest[]{
authorize("create table functional.new_table as " +
"select int_col from functional.alltypes"),
// Explain CTAS.
authorize("explain create table functional.new_table as " +
"select int_col from functional.alltypes")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT))
.ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE,
TPrivilegeLevel.INSERT), onTable("functional", "alltypes",
TPrivilegeLevel.SELECT))
.ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE,
TPrivilegeLevel.INSERT), onColumn("functional", "alltypes", "int_col",
TPrivilegeLevel.ALL))
.ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE,
TPrivilegeLevel.INSERT), onColumn("functional", "alltypes", "int_col",
TPrivilegeLevel.OWNER))
.error(createError("functional"))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.INSERT)),
onTable("functional", "alltypes", TPrivilegeLevel.SELECT))
.error(selectError("functional"), onDatabase("functional",
TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT), onTable("functional",
"alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
}
// Table with a specific location.
authorize("create table functional.new_table(i int) location " +
"'hdfs://localhost:20500/test-warehouse/new_table'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/new_table",
TPrivilegeLevel.OWNER))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.OWNER))
.error(accessError("hdfs://localhost:20500/test-warehouse/new_table"),
onDatabase("functional", TPrivilegeLevel.CREATE));
// External table with URI location.
authorize("create external table functional.new_table(i int) location " +
"'hdfs://localhost:20500/test-warehouse/UPPER_CASE/test'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/UPPER_CASE/test",
TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/UPPER_CASE/test",
TPrivilegeLevel.OWNER))
// Wrong case letters on URI.
.error(accessError("hdfs://localhost:20500/test-warehouse/UPPER_CASE/test"),
onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/upper_case/test",
TPrivilegeLevel.ALL))
.error(accessError("hdfs://localhost:20500/test-warehouse/UPPER_CASE/test"),
onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/upper_case/test",
TPrivilegeLevel.OWNER))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/UPPER_CASE/test", TPrivilegeLevel.ALL))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/UPPER_CASE/test",
TPrivilegeLevel.OWNER))
.error(accessError("hdfs://localhost:20500/test-warehouse/UPPER_CASE/test"),
onDatabase("functional", TPrivilegeLevel.CREATE));
authorize("create table functional.new_table like parquet "
+ "'hdfs://localhost:20500/test-warehouse/schemas/alltypestiny.parquet'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/schemas/alltypestiny.parquet",
TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.CREATE),
onUri("hdfs://localhost:20500/test-warehouse/schemas/alltypestiny.parquet",
TPrivilegeLevel.OWNER))
.error(accessError(
"hdfs://localhost:20500/test-warehouse/schemas/alltypestiny.parquet"),
onServer(allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.CREATE)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/schemas/alltypestiny.parquet",
TPrivilegeLevel.ALL))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/schemas/alltypestiny.parquet",
TPrivilegeLevel.OWNER))
.error(accessError(
"hdfs://localhost:20500/test-warehouse/schemas/alltypestiny.parquet"),
onDatabase("functional", TPrivilegeLevel.CREATE));
authorize("create table if not exists _impala_builtins.new_table(i int)")
.error(systemDbError(), onServer(TPrivilegeLevel.ALL))
.error(systemDbError(), onServer(TPrivilegeLevel.OWNER));
// IMPALA-4000: Only users with ALL/OWNER privileges on SERVER may create external
// Kudu tables.
authorize("create external table functional.kudu_tbl stored as kudu " +
"tblproperties ('kudu.master_addresses'='127.0.0.1', 'kudu.table_name'='tbl')")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.error(createError("functional"))
.error(accessError("server1"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER)))
.error(accessError("server1"), onDatabase("functional", TPrivilegeLevel.ALL))
.error(accessError("server1"), onDatabase("functional", TPrivilegeLevel.OWNER));
// IMPALA-4000: ALL/OWNER privileges on SERVER are not required to create managed
// tables.
authorize("create table functional.kudu_tbl (i int, j int, primary key (i))" +
" partition by hash (i) partitions 9 stored as kudu")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE))
.error(createError("functional"))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
// IMPALA-6451: CTAS for Kudu tables on non-external tables and without
// TBLPROPERTIES ('kudu.master_addresses') should not require ALL/OWNER privileges
// on SERVER.
// The statement below causes the SQL statement to be rewritten.
authorize("create table functional.kudu_tbl primary key (bigint_col) " +
"stored as kudu as " +
"select bigint_col, string_col, current_timestamp() as ins_date " +
"from functional.alltypes " +
"where exists (select 1 from functional.alltypes)")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT))
.error(createError("functional"))
.error(createError("functional"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT,
TPrivilegeLevel.SELECT)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)));
// Database does not exist.
authorize("create table nodb.new_table(i int)")
.error(createError("nodb"))
.error(createError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(createError("nodb"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
}
@Test
public void testCreateView() throws ImpalaException {
for (AuthzTest test: new AuthzTest[]{
authorize("create view functional.new_view as " +
"select int_col from functional.alltypes"),
authorize("create view functional.new_view(a) as " +
"select int_col from functional.alltypes")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE, TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE), onTable(
"functional", "alltypes", TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE), onColumn(
"functional", "alltypes", "int_col", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE), onColumn(
"functional", "alltypes", "int_col", TPrivilegeLevel.OWNER))
.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.SELECT)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(selectError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
}
// View with constant select.
authorize("create view functional.new_view as select 1")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE))
.error(createError("functional"))
.error(createError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.SELECT)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
// View already exists.
for (AuthzTest test: new AuthzTest[]{
authorize("create view functional.alltypes_view as " +
"select int_col from functional.alltypes"),
authorize("create view if not exists functional.alltypes_view as " +
"select int_col from functional.alltypes")}) {
test.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE,
TPrivilegeLevel.SELECT)))
.error(createError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(selectError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
}
authorize("create view if not exists _impala_builtins.new_view as select 1")
.error(systemDbError(), onServer(TPrivilegeLevel.ALL))
.error(systemDbError(), onServer(TPrivilegeLevel.OWNER));
// Database does not exist.
authorize("create view nodb.new_view as select 1")
.error(createError("nodb"))
.error(createError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(createError("nodb"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)));
}
@Test
public void testDropDatabase() throws ImpalaException {
for (AuthzTest test: new AuthzTest[]{
authorize("drop database functional"),
authorize("drop database functional cascade"),
authorize("drop database functional restrict")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.error(dropError("functional"))
.error(dropError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("functional"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.DROP)));
}
// Database does not exist.
for (AuthzTest test: new AuthzTest[]{
authorize("drop database nodb"),
authorize("drop database nodb cascade"),
authorize("drop database nodb restrict")}) {
test.error(dropError("nodb"))
.error(dropError("nodb"), onServer(
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.DROP)));
}
// Database does not exist but with if exists clause.
for (AuthzTest test: new AuthzTest[]{
authorize("drop database if exists nodb"),
authorize("drop database if exists nodb cascade"),
authorize("drop database if exists nodb restrict")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onServer(TPrivilegeLevel.CREATE))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onServer(TPrivilegeLevel.INSERT))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onServer(TPrivilegeLevel.REFRESH))
.error(accessError("nodb"));
}
// Dropping system database is not allowed even if with ALL/OWNER privilege on server.
authorize("drop database _impala_builtins")
.error(systemDbError(), onServer(TPrivilegeLevel.ALL))
.error(systemDbError(), onServer(TPrivilegeLevel.OWNER));
}
@Test
public void testDropTable() throws ImpalaException {
authorize("drop table functional.alltypes")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.DROP))
.error(dropError("functional.alltypes"))
.error(dropError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
// Database/Table does not exist.
authorize("drop table nodb.notbl")
.error(dropError("nodb.notbl"))
.error(dropError("nodb.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("nodb.notbl"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
// Table does not exist.
authorize("drop table functional.notbl")
.error(dropError("functional.notbl"))
.error(dropError("functional.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("functional.notbl"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
// Table does not exist but with if exists clause.
authorize("drop table if exists functional.notbl")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onServer(TPrivilegeLevel.CREATE))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onServer(TPrivilegeLevel.INSERT))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onServer(TPrivilegeLevel.REFRESH))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.REFRESH))
.error(accessError("functional.notbl"));
// Dropping any tables in the system database is not allowed even with ALL/OWNER
// privilege on server.
authorize("drop table _impala_builtins.tbl")
.error(systemDbError(), onServer(TPrivilegeLevel.ALL))
.error(systemDbError(), onServer(TPrivilegeLevel.OWNER));
}
@Test
public void testDropView() throws ImpalaException {
authorize("drop view functional.alltypes_view")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.DROP))
.error(dropError("functional.alltypes_view"))
.error(dropError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("functional.alltypes_view"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.DROP)));
// Database does not exist.
authorize("drop view nodb.noview")
.error(dropError("nodb.noview"))
.error(dropError("nodb.noview"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("nodb.noview"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
// View does not exist.
authorize("drop table functional.noview")
.error(dropError("functional.noview"))
.error(dropError("functional.noview"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)))
.error(dropError("functional.noview"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
// View does not exist but with if exists clause.
authorize("drop table if exists functional.noview")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onServer(TPrivilegeLevel.CREATE))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onServer(TPrivilegeLevel.INSERT))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onServer(TPrivilegeLevel.REFRESH))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.REFRESH))
.error(accessError("functional.noview"));
// Dropping any views in the system database is not allowed even with ALL/OWNER
// privilege on server.
authorize("drop table _impala_builtins.v")
.error(systemDbError(), onServer(TPrivilegeLevel.ALL))
.error(systemDbError(), onServer(TPrivilegeLevel.OWNER));
}
@Test
public void testAlterTable() throws ImpalaException {
BackendConfig.INSTANCE.setZOrderSortUnlocked(true);
for (AuthzTest test: new AuthzTest[]{
authorize("alter table functional.alltypes add column c1 int"),
authorize("alter table functional.alltypes add columns(c1 int)"),
authorize("alter table functional.alltypes replace columns(c1 int)"),
authorize("alter table functional.alltypes change int_col c1 int"),
authorize("alter table functional.alltypes drop int_col"),
authorize("alter table functional.alltypes set fileformat parquet"),
authorize("alter table functional.alltypes set tblproperties('a'='b')"),
authorize("alter table functional.alltypes partition(year=2009) " +
"set tblproperties('a'='b')"),
authorize("alter table functional.alltypes set cached in 'testPool'"),
authorize("alter table functional.alltypes partition(year=2009) set cached " +
"in 'testPool'"),
authorize("alter table functional.alltypes sort by (id)"),
authorize("alter table functional.alltypes sort by zorder (id, bool_col)"),
authorize("alter table functional.alltypes set column stats int_col " +
"('numNulls'='1')"),
authorize("alter table functional.alltypes recover partitions"),
authorize("alter table functional.alltypes set row format delimited fields " +
"terminated by ' '"),
authorize("alter table functional.alltypes partition(year=2009) set row format " +
"delimited fields terminated by ' '"),
authorize("alter table functional.alltypes add partition(year=1, month=1)"),
authorize("alter table functional.alltypes drop partition(" +
"year=2009, month=1)")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes"))
.error(alterError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
}
BackendConfig.INSTANCE.setZOrderSortUnlocked(false);
try {
// We cannot set an owner to a role that doesn't exist
authzCatalog_.addRole("foo_owner");
// Alter table set owner.
for (AuthzTest test : new AuthzTest[]{
authorize("alter table functional.alltypes set owner user foo_owner"),
authorize("alter table functional.alltypes set owner role foo_owner")}) {
test.ok(onServer(true, TPrivilegeLevel.ALL))
.ok(onServer(true, TPrivilegeLevel.OWNER))
.ok(onDatabase(true, "functional", TPrivilegeLevel.ALL))
.ok(onDatabase(true, "functional", TPrivilegeLevel.OWNER))
.ok(onTable(true, "functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable(true, "functional", "alltypes", TPrivilegeLevel.OWNER))
.error(accessError(true, "functional.alltypes"))
.error(accessError(true, "functional.alltypes"), onServer(true, allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError(true, "functional.alltypes"), onDatabase(true,
"functional", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError(true, "functional.alltypes"),
onTable(true, "functional", "alltypes", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
// TODO: Checking if a request is allowed by checking if grant option flag is set
// is to Sentry.
// The following do not result in Ranger authorization errors.
if (authzProvider_ == AuthorizationProvider.SENTRY) {
test.error(accessError(true, "functional.alltypes"), onServer(
TPrivilegeLevel.values()))
.error(accessError(true, "functional.alltypes"), onDatabase("functional",
TPrivilegeLevel.values()))
.error(accessError(true, "functional.alltypes"), onTable("functional",
"alltypes", TPrivilegeLevel.values()));
} else {
test.ok(onServer(TPrivilegeLevel.values()));
test.ok(onDatabase("functional", TPrivilegeLevel.values()));
test.ok(onTable("functional", "alltypes", TPrivilegeLevel.values()));
}
}
} finally {
authzCatalog_.removeRole("foo_owner");
}
boolean exceptionThrown = false;
try {
parseAndAnalyze("alter table functional.alltypes set owner role foo_owner",
authzCtx_, frontend_);
} catch (AnalysisException e) {
exceptionThrown = true;
assertEquals("Role 'foo_owner' does not exist.", e.getLocalizedMessage());
}
assertTrue(exceptionThrown);
// Alter table rename.
authorize("alter table functional.alltypes rename to functional_parquet.new_table")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL),
onDatabase("functional_parquet", TPrivilegeLevel.CREATE))
.ok(onDatabase("functional_parquet", TPrivilegeLevel.CREATE),
onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER),
onDatabase("functional_parquet", TPrivilegeLevel.CREATE))
.ok(onDatabase("functional_parquet", TPrivilegeLevel.CREATE),
onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.error(accessError("functional.alltypes"))
.error(accessError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(accessError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)), onDatabase("functional_parquet",
TPrivilegeLevel.CREATE))
.error(createError("functional_parquet"), onDatabase("functional",
TPrivilegeLevel.ALL), onDatabase("functional_parquet", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(accessError("functional.alltypes"), onDatabase("functional",
TPrivilegeLevel.CREATE), onTable("functional", "alltypes", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(createError("functional_parquet"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)),
onTable("functional", "alltypes", TPrivilegeLevel.ALL));
// Only for Kudu tables.
for (AuthzTest test: new AuthzTest[]{
authorize("alter table functional_kudu.testtbl alter column " +
"name drop default"),
authorize("alter table functional_kudu.testtbl alter column name " +
"set default null"),
authorize("alter table functional_kudu.testtbl add range partition " +
"1 < values < 2"),
authorize("alter table functional_kudu.testtbl drop range partition " +
"1 < values < 2")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.ALL))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.ALTER))
.ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.ALL))
.ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.OWNER))
.ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.ALTER))
.error(alterError("functional_kudu.testtbl"))
.error(alterError("functional_kudu.testtbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional_kudu.testtbl"), onDatabase("functional_kudu",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)))
.error(alterError("functional_kudu.testtbl"), onTable("functional_kudu",
"testtbl", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
}
// Alter table set location.
for (AuthzTest test: new AuthzTest[] {
authorize("alter table functional.alltypes set location " +
"'hdfs://localhost:20500/test-warehouse/new_table'"),
authorize("alter table functional.alltypes partition(year=2009, month=1) " +
"set location 'hdfs://localhost:20500/test-warehouse/new_table'")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.ALTER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER), onUri(
"hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.OWNER))
.error(alterError("functional.alltypes"))
.error(alterError("functional.alltypes"),
onServer(allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)),
onUri("hdfs://localhost:20500/test-warehouse/new_table"))
.error(alterError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)),
onUri("hdfs://localhost:20500/test-warehouse/new_table"))
.error(alterError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)),
onUri("hdfs://localhost:20500/test-warehouse/new_table"))
.error(accessError("hdfs://localhost:20500/test-warehouse/new_table"),
onDatabase("functional", TPrivilegeLevel.ALTER))
.error(accessError("hdfs://localhost:20500/test-warehouse/new_table"),
onTable("functional", "alltypes", TPrivilegeLevel.ALTER));
}
// Database does not exist.
authorize("alter table nodb.alltypes add columns(c1 int)")
.error(alterError("nodb"))
.error(alterError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
// Table does not exist.
authorize("alter table functional.notbl add columns(c1 int)")
.error(alterError("functional.notbl"))
.error(alterError("functional.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.notbl"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
}
@Test
public void testAlterView() throws ImpalaException {
for (AuthzTest test: new AuthzTest[] {
authorize("alter view functional.alltypes_view as " +
"select int_col from functional.alltypes"),
authorize("alter view functional.alltypes_view(a) as " +
"select int_col from functional.alltypes")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER), onTable("functional", "alltypes",
TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER),
onTable("functional", "alltypes", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"))
.error(selectError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)))
.error(selectError("functional.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.SELECT)))
.error(alterError("functional.alltypes_view"), onTable("functional", "alltypes",
TPrivilegeLevel.SELECT), onTable("functional", "alltypes_view", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(selectError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)),
onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER));
}
// Alter view rename.
authorize("alter view functional.alltypes_view rename to functional_parquet.new_view")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL),
onDatabase("functional_parquet", TPrivilegeLevel.CREATE))
.ok(onDatabase("functional_parquet", TPrivilegeLevel.CREATE),
onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER),
onDatabase("functional_parquet", TPrivilegeLevel.CREATE))
.ok(onDatabase("functional_parquet", TPrivilegeLevel.CREATE),
onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.error(accessError("functional.alltypes_view"))
.error(accessError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(accessError("functional.alltypes_view"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)),
onDatabase("functional_parquet", TPrivilegeLevel.CREATE))
.error(createError("functional_parquet"), onDatabase("functional",
TPrivilegeLevel.ALL), onDatabase("functional_parquet", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)))
.error(accessError("functional.alltypes_view"), onDatabase("functional",
TPrivilegeLevel.CREATE), onTable("functional", "alltypes_view", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(createError("functional_parquet"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)),
onTable("functional", "alltypes_view", TPrivilegeLevel.ALL));
// Alter view with constant select.
authorize("alter view functional.alltypes_view as select 1")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes_view"))
.error(alterError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes_view"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
try {
// We cannot set an owner to a role that doesn't exist
authzCatalog_.addRole("foo_owner");
// Alter view set owner.
for (AuthzTest test : new AuthzTest[]{
authorize("alter view functional.alltypes_view set owner user foo_owner"),
authorize("alter view functional.alltypes_view set owner role foo_owner")}) {
test.ok(onServer(true, TPrivilegeLevel.ALL))
.ok(onServer(true, TPrivilegeLevel.OWNER))
.ok(onDatabase(true, "functional", TPrivilegeLevel.ALL))
.ok(onDatabase(true, "functional", TPrivilegeLevel.OWNER))
.ok(onTable(true, "functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onTable(true, "functional", "alltypes_view", TPrivilegeLevel.OWNER))
.error(accessError(true, "functional.alltypes_view"))
.error(accessError(true, "functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError(true, "functional.alltypes_view"), onDatabase(
"functional", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError(true, "functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER)));
// TODO: Checking if a request is allowed by checking if grant option flag is set
// is to Sentry.
// The following do not result in Ranger authorization errors.
if (authzProvider_ == AuthorizationProvider.SENTRY) {
test.error(accessError(true, "functional.alltypes_view"), onServer(
TPrivilegeLevel.values()))
.error(accessError(true, "functional.alltypes_view"), onDatabase(
"functional", TPrivilegeLevel.values()))
.error(accessError(true, "functional.alltypes_view"), onTable("functional",
"alltypes_view", TPrivilegeLevel.values()));
} else {
test.ok(onServer(TPrivilegeLevel.values()));
test.ok(onDatabase("functional", TPrivilegeLevel.values()));
test.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.values()));
}
}
} finally {
authzCatalog_.removeRole("foo_owner");
}
// Database does not exist.
authorize("alter view nodb.alltypes_view as select 1")
.error(alterError("nodb"))
.error(alterError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
// View does not exist.
authorize("alter view functional.noview as select 1")
.error(alterError("functional.noview"))
.error(alterError("functional.noview"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.noview"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
}
@Test
public void testAlterDatabase() throws ImpalaException {
try {
// We cannot set an owner to a role that doesn't exist
authzCatalog_.addRole("foo");
// Alter database set owner.
for (String ownerType : new String[]{"user", "role"}) {
authorize(String.format("alter database functional set owner %s foo",
ownerType))
.ok(onServer(true, TPrivilegeLevel.ALL))
.ok(onServer(true, TPrivilegeLevel.OWNER))
.ok(onDatabase(true, "functional", TPrivilegeLevel.ALL))
.ok(onDatabase(true, "functional", TPrivilegeLevel.OWNER))
.error(accessError(true, "functional"))
.error(accessError(true, "functional"), onServer(true, allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError(true, "functional"), onDatabase(true, "functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
// TODO: Checking if a request is allowed by checking if grant option flag is set
// is to Sentry.
// The following do not result in Ranger authorization errors.
if (authzProvider_ == AuthorizationProvider.SENTRY) {
authorize(String.format("alter database functional set owner %s foo",
ownerType))
.error(accessError(true, "functional"), onServer(TPrivilegeLevel.values()))
.error(accessError(true, "functional"), onDatabase("functional",
TPrivilegeLevel.values()));
} else {
authorize(String.format("alter database functional set owner %s foo",
ownerType))
.ok(onServer(TPrivilegeLevel.values()))
.ok(onDatabase("functional", TPrivilegeLevel.values()));
}
// Database does not exist.
authorize(String.format("alter database nodb set owner %s foo", ownerType))
.error(accessError(true, "nodb"))
.error(accessError(true, "nodb"), onServer(true, allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
}
} finally {
authzCatalog_.removeRole("foo");
}
boolean exceptionThrown = false;
try {
parseAndAnalyze("alter database functional set owner role foo",
authzCtx_, frontend_);
} catch (AnalysisException e) {
exceptionThrown = true;
assertEquals("Role 'foo' does not exist.", e.getLocalizedMessage());
}
assertTrue(exceptionThrown);
}
@Test
public void testUpdate() throws ImpalaException {
// Update is only supported on Kudu tables.
for (AuthzTest test: new AuthzTest[]{
authorize("update functional_kudu.alltypes set int_col = 1"),
// Explain update.
authorize("explain update functional_kudu.alltypes set int_col = 1")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.ALL))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.OWNER))
.ok(onTable("functional_kudu", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional_kudu", "alltypes", TPrivilegeLevel.OWNER))
.error(accessError("functional_kudu.alltypes"))
.error(accessError("functional_kudu.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.alltypes"), onTable(
"functional", "alltypes", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
}
// Database does not exist.
authorize("update nodb.alltypes set int_col = 1")
.error(selectError("nodb"))
.error(selectError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)));
// Table does not exist.
authorize("update functional_kudu.notbl set int_col = 1")
.error(selectError("functional_kudu.notbl"))
.error(selectError("functional_kudu.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional_kudu.notbl"), onDatabase("functional_kudu",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
}
@Test
public void testUpsert() throws ImpalaException {
// Upsert is only supported on Kudu tables.
for (AuthzTest test: new AuthzTest[]{
authorize("upsert into table functional_kudu.testtbl(id, name) values(1, 'a')"),
// Upsert with clause.
authorize("with t1 as (select 1, 'a', 2) upsert into functional_kudu.testtbl " +
"select * from t1"),
// Explain upsert.
authorize("explain upsert into table functional_kudu.testtbl(id, name) " +
"values(1, 'a')")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.ALL))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.OWNER))
.ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.ALL))
.ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.OWNER))
.error(accessError("functional_kudu.testtbl"))
.error(accessError("functional_kudu.testtbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.testtbl"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.testtbl"), onTable(
"functional", "testtbl", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
}
// Upsert select.
authorize("upsert into table functional_kudu.testtbl(id) " +
"select int_col from functional.alltypes")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.ALL),
onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.ALL),
onTable("functional", "alltypes", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"))
.error(accessError("functional_kudu.testtbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.testtbl"),
onDatabase("functional_kudu", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)),
onDatabase("functional", TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes"),
onTable("functional_kudu", "testtbl", TPrivilegeLevel.ALL),
onTable("functional", "alltypes", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(accessError("functional_kudu.testtbl"),
onTable("functional_kudu", "testtbl", allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER)),
onTable("functional", "alltypes", TPrivilegeLevel.SELECT));
// Database does not exist.
authorize("upsert into table nodb.testtbl(id, name) values(1, 'a')")
.error(accessError("nodb.testtbl"))
.error(accessError("nodb.testtbl"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER)));
// Table does not exist.
authorize("upsert into table functional_kudu.notbl(id, name) values(1, 'a')")
.error(accessError("functional_kudu.notbl"))
.error(accessError("functional_kudu.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.notbl"), onDatabase("functional_kudu",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
}
@Test
public void testDelete() throws ImpalaException {
// Delete is only supported on Kudu tables.
for (AuthzTest test: new AuthzTest[]{
authorize("delete from functional_kudu.alltypes"),
authorize("explain delete from functional_kudu.alltypes")}) {
test.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.ALL))
.ok(onDatabase("functional_kudu", TPrivilegeLevel.OWNER))
.ok(onTable("functional_kudu", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional_kudu", "alltypes", TPrivilegeLevel.OWNER))
.error(accessError("functional_kudu.alltypes"))
.error(accessError("functional_kudu.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.alltypes"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(accessError("functional_kudu.alltypes"), onTable(
"functional", "alltypes", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
}
// Database does not exist.
authorize("delete from nodb.alltypes")
.error(selectError("nodb"))
.error(selectError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)));
// Table does not exist.
authorize("delete from functional_kudu.notbl")
.error(selectError("functional_kudu.notbl"))
.error(selectError("functional_kudu.notbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
.error(selectError("functional_kudu.notbl"), onDatabase("functional_kudu",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT)));
}
@Test
public void testCommentOn() throws ImpalaException {
// Comment on database.
authorize("comment on database functional is 'comment'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.error(alterError("functional"))
.error(alterError("functional"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
// Comment on table.
authorize("comment on table functional.alltypes is 'comment'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes"))
.error(alterError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
// Comment on view.
authorize("comment on view functional.alltypes_view is 'comment'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes_view"))
.error(alterError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes_view"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
// Comment on table column.
authorize("comment on column functional.alltypes.id is 'comment'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes"))
.error(alterError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes"), onTable("functional", "alltypes",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
// Comment on view column.
authorize("comment on column functional.alltypes_view.id is 'comment'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes_view"))
.error(alterError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes_view"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(alterError("functional.alltypes_view"), onTable("functional",
"alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.ALTER)));
}
@Test
public void testFunction() throws ImpalaException {
// Create function.
authorize("create function functional.f() returns int location " +
"'/test-warehouse/libTestUdfs.so' symbol='NoArgs'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE), onUri("/test-warehouse/libTestUdfs.so",
TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.CREATE), onUri("/test-warehouse/libTestUdfs.so",
TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.OWNER))
.error(createFunctionError("functional.f()"))
.error(accessError("hdfs://localhost:20500/test-warehouse/libTestUdfs.so"),
onServer(allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(createFunctionError("functional.f()"),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL))
.error(createFunctionError("functional.f()"),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.OWNER));
// Create a function name that has the same name as built-in function is OK.
authorize("create function functional.sin() returns int location " +
"'/test-warehouse/libTestUdfs.so' symbol='NoArgs'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE), onUri("/test-warehouse/libTestUdfs.so",
TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.CREATE), onUri("/test-warehouse/libTestUdfs.so",
TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALL),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.OWNER))
.error(createFunctionError("functional.sin()"))
.error(accessError("hdfs://localhost:20500/test-warehouse/libTestUdfs.so"),
onServer(allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)))
.error(createFunctionError("functional.sin()"),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL))
.error(createFunctionError("functional.sin()"),
onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.OWNER));
// Creating a function in the system database even with ALL/OWNER privilege on SERVER
// is not allowed.
for (AuthzTest test: new AuthzTest[] {
authorize("create function _impala_builtins.sin() returns int location " +
"'/test-warehouse/libTestUdfs.so' symbol='NoArgs'"),
authorize("create function _impala_builtins.f() returns int location " +
"'/test-warehouse/libTestUdfs.so' symbol='NoArgs'")}) {
test.error(systemDbError(), onServer(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER));
}
ScalarFunction fn = addFunction("functional", "f");
try {
authorize("drop function functional.f()")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.error(dropFunctionError("functional.f()"))
.error(dropFunctionError("functional.f()"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
// Function does not exist but with if exists clause.
authorize("drop function if exists functional.g()")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.DROP))
.ok(onServer(TPrivilegeLevel.CREATE))
.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onServer(TPrivilegeLevel.INSERT))
.ok(onServer(TPrivilegeLevel.ALTER))
.ok(onServer(TPrivilegeLevel.REFRESH))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.INSERT))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER))
.ok(onDatabase("functional", TPrivilegeLevel.REFRESH))
.error(accessFunctionError("functional.g()"));
} finally {
removeFunction(fn);
}
// IMPALA-6086: Make sure use of a permanent function requires SELECT (or higher)
// privilege on the database, and expr rewrite/constant-folding preserves
// privilege requests for functions.
List<Type> argTypes = new ArrayList<Type>();
argTypes.add(Type.STRING);
fn = addFunction("functional", "to_lower", argTypes, Type.STRING,
"/test-warehouse/libTestUdf.so",
"_Z7ToLowerPN10impala_udf15FunctionContextERKNS_9StringValE");
try {
TQueryOptions options = new TQueryOptions();
options.setEnable_expr_rewrites(true);
for (AuthzTest test: new AuthzTest[] {
authorize("select functional.to_lower('ABCDEF')"),
// Also test with expression rewrite enabled. Notice that when creating an
// analysis context, we have to explicitly specify the requesting user
// corresponding to 'user_' defined in AuthorizationTestBase.java. Otherwise,
// an analysis context will be created with a user corresponding to
// User(System.getProperty("user.name")), resulting in a Sentry authorization
// error.
authorize(createAnalysisCtx(options, authzFactory_, user_.getName()),
"select functional.to_lower('ABCDEF')")
}) {
test.ok(onServer(TPrivilegeLevel.SELECT))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", viewMetadataPrivileges()))
.error(accessError("functional"))
.error(accessError("functional"), onDatabase("functional",
allExcept(viewMetadataPrivileges())));
}
} finally {
removeFunction(fn);
}
}
@Test
public void testShutdown() throws ImpalaException {
// Requires ALL privilege on server.
authorize(": shutdown()")
.ok(onServer(TPrivilegeLevel.ALL))
.error(accessError("server"))
.error(accessError("server"), onServer(TPrivilegeLevel.REFRESH))
.error(accessError("server"), onServer(TPrivilegeLevel.SELECT))
.error(accessError("server"), onDatabase("functional", TPrivilegeLevel.ALL))
.error(accessError("server"),
onTable("functional", "alltypes", TPrivilegeLevel.ALL));
}
@Test
public void testRowFilterEnabled() throws ImpalaException {
if (authzProvider_ == AuthorizationProvider.SENTRY) return;
String policyName = "row_filter";
for (String tableName: new String[]{"alltypes", "alltypes_view"}) {
String json = String.format("{\n" +
" \"name\": \"%s\",\n" +
" \"policyType\": 2,\n" +
" \"serviceType\": \"%s\",\n" +
" \"service\": \"%s\",\n" +
" \"resources\": {\n" +
" \"database\": {\n" +
" \"values\": [\"functional\"],\n" +
" \"isExcludes\": false,\n" +
" \"isRecursive\": false\n" +
" },\n" +
" \"table\": {\n" +
" \"values\": [\"%s\"],\n" +
" \"isExcludes\": false,\n" +
" \"isRecursive\": false\n" +
" }\n" +
" },\n" +
" \"rowFilterPolicyItems\": [\n" +
" {\n" +
" \"accesses\": [\n" +
" {\n" +
" \"type\": \"select\",\n" +
" \"isAllowed\": true\n" +
" }\n" +
" ],\n" +
" \"users\": [\"%s\"],\n" +
" \"rowFilterInfo\": {\"filterExpr\": \"id = 0\"}\n" +
" }\n" +
" ]\n" +
"}", policyName, RANGER_SERVICE_TYPE, RANGER_SERVICE_NAME, tableName,
user_.getShortName());
try {
createRangerPolicy(policyName, json);
rangerImpalaPlugin_.refreshPoliciesAndTags();
// Queries on tables that are not filtered should be allowed.
authorize("select string_col from functional_kudu.alltypes")
.ok(onServer(TPrivilegeLevel.ALL));
authorize("select x from functional.alltypes_view_sub")
.ok(onServer(TPrivilegeLevel.ALL));
// Normal select.
authorize(String.format("select string_col from functional.%s", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Select with *.
authorize(String.format("select * from functional.%s", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Sub-query.
authorize(String.format(
"select t.string_col from (select * from functional.%s) t", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// CTE.
authorize(String.format("with t as (select * from functional.%s) " +
"select string_col from t", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// CTAS.
authorize(String.format(
"create table t as select * from functional.%s", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Create view.
authorize(String.format(
"create view v as select * from functional.%s", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Alter view.
authorize(String.format("alter view functional.alltypes_view_sub as " +
"select * from functional.%s", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Union.
authorize(String.format(
"select string_col from functional.%s union select 'hello'", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Update.
authorize(String.format(
"update functional_kudu.alltypes set int_col = 1 where string_col in " +
"(select string_col from functional.%s)", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Delete.
authorize(String.format("delete functional_kudu.alltypes where string_col in " +
"(select string_col from functional.%s)", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
// Copy testcase.
authorize(String.format(
"copy testcase to '/tmp' select * from functional.%s", tableName))
.error(rowFilterError(String.format("functional.%s", tableName)),
onServer(TPrivilegeLevel.ALL));
} finally {
deleteRangerPolicy(policyName);
}
}
}
/**
* Validates Ranger's object ownership privileges. Note that we no longer have to add a
* policy to the Ranger server to explicitly grant a user the access privileges of the
* resources if the user is the owner of the resources.
*/
@Test
public void testRangerObjectOwnership() throws Exception {
if (authzProvider_ == AuthorizationProvider.SENTRY) return;
// 'as_owner_' is by default set to false for AuthorizationTestBase. But since this
// test is meant for testing Ranger's behavior when the requesting user is the owner
// of the resources, we set 'as_owner_' to true.
as_owner_ = true;
TQueryOptions options = new TQueryOptions();
ImmutableSet<AuthzTest> testQueries = ImmutableSet
.<AuthzTest>builder()
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"select count(*) from functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"select id from functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"select id from functional.alltypes_view"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"show create table functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"describe functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"show create table functional.alltypes_view"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"describe functional.alltypes_view"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"describe functional.allcomplextypes.int_struct_col"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"refresh functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"invalidate metadata functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"compute stats functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"drop stats functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"create table functional.test_tbl(a int)"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"create table functional.test_tbl like functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"create table functional.test_tbl as select 1"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"create view functional.test_view as select 1"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"alter table functional.alltypes add column c1 int"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"drop table functional.alltypes"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"drop view functional.alltypes_view"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"alter view functional.alltypes_view as select 1"))
.add(authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"alter database functional set owner user foo"))
.build();
// Run the queries.
for (AuthzTest authz: testQueries) authz.ok();
// Tests for more fine grained {OWNER} privileges.
//
// SELECT privilege.
authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"select count(*) from functional.alltypes").ok();
authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"select count(*) from functional.alltypes_view").ok();
// The owner is granted all privileges in the following by default.
try {
authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"select count(*) from functional.alltypes").ok();
authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"alter table functional.alltypes add column c1 int").ok();
authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"drop table functional.alltypes").ok();
authorize(createAnalysisCtx(options, authzFactory_,
OWNER_USER.getName()),
"select count(*) from functional.alltypes_view").ok();
} finally {
as_owner_ = false;
}
}
private void createOwnerPolicy(String policyName, String privilege,
String db, String tbl, String col) throws Exception {
// Template policy that grants privileges on a given db/tbl/column to it's
// owner.
final String createOwnerPolicyTemplate = "{\n" +
" \"isAuditEnabled\": true,\n" +
" \"isDenyAllElse\": false,\n" +
" \"isEnabled\": true,\n" +
" \"name\": \"%s\",\n" + // policy name
" \"policyItems\": [\n" +
" {\n" +
" \"accesses\": [\n" +
" {\n" +
" \"isAllowed\": true,\n" +
" \"type\": \"%s\"\n" + // privilege to grant
" }\n" +
" ],\n" +
" \"delegateAdmin\": false,\n" +
" \"users\": [\n" +
" \"{OWNER}\"\n" + // {OWNER} access
" ]\n" +
" }\n" +
" ],\n" +
" \"policyPriority\": 0,\n" +
" \"policyType\": 0,\n" +
" \"resources\": {\n" +
" \"column\": {\n" +
" \"isExcludes\": false,\n" +
" \"isRecursive\": false,\n" +
" \"values\": [\n" +
" \"%s\"\n" + // column name
" ]\n" +
" },\n" +
" \"database\": {\n" +
" \"isExcludes\": false,\n" +
" \"isRecursive\": false,\n" +
" \"values\": [\n" +
" \"%s\"\n" + // database name
" ]\n" +
" },\n" +
" \"table\": {\n" +
" \"isExcludes\": false,\n" +
" \"isRecursive\": false,\n" +
" \"values\": [\n" +
" \"%s\"\n" + // table name
" ]\n" +
" }\n" +
" },\n" +
" \"service\": \"%s\",\n" + // service name
" \"serviceType\": \"%s\"\n" + // service type
"}";
String policyRequest = String.format(createOwnerPolicyTemplate,
policyName, privilege, col, db, tbl, RANGER_SERVICE_NAME, RANGER_SERVICE_TYPE);
// Some old policies may exist on the same db/tbl/col combination due to other test
// runs. We clean them up and retry in that case.
try {
createRangerPolicy(policyName, policyRequest);
} catch (RuntimeException e) {
if (!e.getMessage().contains("Another policy already exists")) throw e;
LOG.info("Another policy exists for the given resource, deleting it", e);
// Look for policy-name=[*]
Pattern pattern = Pattern.compile("policy-name=\\[(.*?)\\]");
Matcher m = pattern.matcher(e.getMessage());
assertTrue(m.find());
LOG.info("Deleting policy: " + m.group(1));
deleteRangerPolicy(m.group(1));
createRangerPolicy(policyName, policyRequest);
}
}
private void verifyPrivilegeReqs(String stmt, Set<String> expectedPrivilegeNames)
throws ImpalaException {
verifyPrivilegeReqs(createAnalysisCtx(authzFactory_), stmt, expectedPrivilegeNames);
}
private void verifyPrivilegeReqs(AnalysisContext ctx, String stmt,
Set<String> expectedPrivilegeNames) throws ImpalaException {
AnalysisResult analysisResult = parseAndAnalyze(stmt, ctx, frontend_);
Set<String> actualPrivilegeNames = new HashSet<>();
for (PrivilegeRequest privReq: analysisResult.getAnalyzer().getPrivilegeReqs()) {
actualPrivilegeNames.add(privReq.getName());
}
assertEquals(expectedPrivilegeNames, actualPrivilegeNames);
}
}