blob: 7e10eeee895276990bc5acb95ef8cdcbcab08cd9 [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.analysis;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import org.apache.commons.lang.ArrayUtils;
import org.apache.impala.analysis.AnalysisContext.AnalysisResult;
import org.apache.impala.authorization.AuthorizationConfig;
import org.apache.impala.authorization.PrivilegeRequest;
import org.apache.impala.authorization.User;
import org.apache.impala.catalog.AuthorizationException;
import org.apache.impala.catalog.PrincipalPrivilege;
import org.apache.impala.catalog.Role;
import org.apache.impala.catalog.ScalarFunction;
import org.apache.impala.catalog.Type;
import org.apache.impala.common.FrontendTestBase;
import org.apache.impala.common.ImpalaException;
import org.apache.impala.common.RuntimeEnv;
import org.apache.impala.service.Frontend;
import org.apache.impala.testutil.ImpaladTestCatalog;
import org.apache.impala.thrift.TColumnValue;
import org.apache.impala.thrift.TDescribeOutputStyle;
import org.apache.impala.thrift.TDescribeResult;
import org.apache.impala.thrift.TFunctionBinaryType;
import org.apache.impala.thrift.TPrincipalType;
import org.apache.impala.thrift.TPrivilege;
import org.apache.impala.thrift.TPrivilegeLevel;
import org.apache.impala.thrift.TPrivilegeScope;
import org.apache.impala.thrift.TQueryOptions;
import org.apache.impala.thrift.TResultRow;
import org.apache.impala.thrift.TTableName;
import org.apache.impala.util.SentryPolicyService;
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 java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* This class contains authorization tests for SQL statements.
*/
public class AuthorizationStmtTest extends FrontendTestBase {
private static final String SENTRY_SERVER = "server1";
private static final User USER = new User(System.getProperty("user.name"));
private final AnalysisContext analysisContext_;
private final SentryPolicyService sentryService_;
private final ImpaladTestCatalog authzCatalog_;
private final Frontend authzFrontend_;
public AuthorizationStmtTest() {
AuthorizationConfig authzConfig = AuthorizationConfig.createHadoopGroupAuthConfig(
SENTRY_SERVER, null, System.getenv("IMPALA_HOME") +
"/fe/src/test/resources/sentry-site.xml");
authzConfig.validateConfig();
analysisContext_ = createAnalysisCtx(authzConfig, USER.getName());
authzCatalog_ = new ImpaladTestCatalog(authzConfig);
authzFrontend_ = new Frontend(authzConfig, authzCatalog_);
sentryService_ = new SentryPolicyService(authzConfig.getSentryConfig());
}
@BeforeClass
public static void setUp() {
RuntimeEnv.INSTANCE.setTestEnv(true);
}
@AfterClass
public static void cleanUp() {
RuntimeEnv.INSTANCE.reset();
}
@Before
public void before() throws ImpalaException {
// Remove existing roles in order to not interfere with these tests.
for (TSentryRole role: sentryService_.listAllRoles(USER)) {
authzCatalog_.removeRole(role.getRoleName());
}
}
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 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.
// Column-level privileges on views are not currently supported.
authorize("select id from functional.alltypes_view")
.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))
.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.
// Column-level privileges on views are not currently supported.
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))
.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.
// Column-level privileges on views are not currently supported.
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))
.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 on server.
authorize("invalidate metadata")
.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 should always be allowed.
try {
authzCatalog_.addRole("test_role");
authorize("show grant role test_role").ok();
authorize("show grant role test_role on server").ok();
authorize("show grant role test_role on database functional").ok();
authorize("show grant role test_role on table functional.alltypes").ok();
authorize("show grant role test_role on uri '/test-warehouse'").ok();
} finally {
authzCatalog_.removeRole("test_role");
}
// 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, style, ALLTYPES_COLUMNS, null, onServer(privilege))
.okDescribe(tableName, style, ALLTYPES_COLUMNS, null, onDatabase("functional",
privilege))
.okDescribe(tableName, style, ALLTYPES_COLUMNS, null, onTable("functional",
"alltypes", privilege));
}
authzTest.okDescribe(tableName, style, null, ALLTYPES_COLUMNS, onServer(
allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, style, null, ALLTYPES_COLUMNS, onDatabase("functional",
allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, style, null, ALLTYPES_COLUMNS, onTable("functional",
"alltypes", allExcept(viewMetadataPrivileges())))
// 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, style, new String[]{"id"}, ALLTYPES_COLUMNS_WITHOUT_ID,
onColumn("functional", "alltypes", "id", TPrivilegeLevel.SELECT))
.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, style, checkStrings, null, onServer(privilege))
.okDescribe(tableName, style, checkStrings, null, onDatabase("functional",
privilege))
.okDescribe(tableName, style, checkStrings, null, onTable("functional",
"alltypes", privilege));
}
// Describe table without VIEW_METADATA privilege should not show all columns and
// location.
authzTest.okDescribe(tableName, style, null, ALLTYPES_COLUMNS,
onServer(allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, style, null, ALLTYPES_COLUMNS,
onDatabase("functional", allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, style, null, ALLTYPES_COLUMNS,
onTable("functional", "alltypes", allExcept(viewMetadataPrivileges())))
// Location should not appear with only column level auth.
.okDescribe(tableName, style, new String[]{"id"},
(String[]) ArrayUtils.addAll(ALLTYPES_COLUMNS_WITHOUT_ID,
new String[]{"Location:"}), onColumn("functional", "alltypes", "id",
TPrivilegeLevel.SELECT))
.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, style, ALLTYPES_COLUMNS, null, onServer(privilege))
.okDescribe(tableName, style, ALLTYPES_COLUMNS, null, onDatabase("functional",
privilege))
.okDescribe(tableName, style, ALLTYPES_COLUMNS, null, onTable("functional",
"alltypes_view", privilege));
}
authzTest.okDescribe(tableName, style, null, ALLTYPES_COLUMNS, onServer(
allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, style, null, ALLTYPES_COLUMNS, onDatabase("functional",
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, style, checkStrings, null, onServer(privilege))
.okDescribe(tableName, style, checkStrings, null, onDatabase("functional",
privilege))
.okDescribe(tableName, style, checkStrings, null, onTable("functional",
"alltypes_view", privilege));
}
authzTest.okDescribe(tableName, style, null, ALLTYPES_COLUMNS, onServer(
allExcept(viewMetadataPrivileges())))
.okDescribe(tableName, style, null, ALLTYPES_COLUMNS, onDatabase("functional",
allExcept(viewMetadataPrivileges())))
.error(accessError("functional.alltypes_view"));
// Describe specific column on a table.
authzTest = authorize("describe functional.allcomplextypes.int_struct_col");
for (TPrivilegeLevel privilege: TPrivilegeLevel.values()) {
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.
authorize("create database newdb location " +
"'hdfs://localhost:20500/test-warehouse/new_location'")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.CREATE), onUri(
"hdfs://localhost:20500/test-warehouse/new_location", TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.CREATE), onUri(
"hdfs://localhost:20500/test-warehouse/new_location", TPrivilegeLevel.OWNER))
.error(createError("newdb"))
.error(createError("newdb"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/new_location", TPrivilegeLevel.ALL))
.error(createError("newdb"), onServer(allExcept(TPrivilegeLevel.ALL,
TPrivilegeLevel.OWNER, TPrivilegeLevel.CREATE)), onUri(
"hdfs://localhost:20500/test-warehouse/new_location", TPrivilegeLevel.OWNER))
.error(accessError("hdfs://localhost:20500/test-warehouse/new_location"),
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))
.error(dropError("nodb"))
.error(dropError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
}
// 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(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.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)));
// 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(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.DROP))
.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)));
// 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 {
for (AuthzTest test: new AuthzTest[]{
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 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)"),
authorize("alter table functional.alltypes set owner user foo_owner"),
authorize("alter table functional.alltypes set owner role foo_owner")}) {
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.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)));
}
// Alter table rename.
authorize("alter table functional.alltypes rename to functional.new_table")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE), onTable("functional",
"alltypes", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes"))
.error(alterError("functional.alltypes"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.CREATE)))
.error(alterError("functional.alltypes"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.CREATE)))
.error(alterError("functional.alltypes"), onDatabase("functional",
TPrivilegeLevel.CREATE), onTable("functional", "alltypes", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(createError("functional"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.CREATE)),
onTable("functional", "alltypes", TPrivilegeLevel.ALTER));
// 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.new_view")
.ok(onServer(TPrivilegeLevel.ALL))
.ok(onServer(TPrivilegeLevel.OWNER))
.ok(onServer(TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.ALL))
.ok(onDatabase("functional", TPrivilegeLevel.OWNER))
.ok(onDatabase("functional", TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))
.ok(onDatabase("functional", TPrivilegeLevel.CREATE), onTable("functional",
"alltypes_view", TPrivilegeLevel.ALTER))
.error(alterError("functional.alltypes_view"))
.error(alterError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.CREATE)))
.error(alterError("functional.alltypes_view"), onDatabase("functional", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER,
TPrivilegeLevel.CREATE)))
.error(alterError("functional.alltypes_view"), onDatabase("functional",
TPrivilegeLevel.CREATE), onTable("functional", "alltypes_view", allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)))
.error(createError("functional"), onDatabase("functional",
allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.CREATE)), onTable("functional", "alltypes_view",
TPrivilegeLevel.ALTER));
// 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)));
// 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(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)));
}
// 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 {
for (String ownerType: new String[]{"user", "role"}) {
authorize(String.format("alter database functional set owner %s foo", ownerType))
.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)));
// Database does not exist.
authorize(String.format("alter database nodb set owner %s foo", ownerType))
.error(alterError("nodb"))
.error(alterError("nodb"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.ALTER)));
}
}
@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))
.error(accessError("functional_kudu.alltypes"))
.error(accessError("functional_kudu.alltypes"), onServer(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))
.error(accessError("functional_kudu.testtbl"))
.error(accessError("functional_kudu.testtbl"), onServer(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))
.error(selectError("functional.alltypes"))
.error(accessError("functional_kudu.testtbl"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER)));
// 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))
.error(accessError("functional_kudu.alltypes"))
.error(accessError("functional_kudu.alltypes"), onServer(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()")
.error(dropFunctionError("functional.g()"))
.error(dropFunctionError("functional.g()"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.DROP)));
} 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.
ArrayList<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.
authorize(createAnalysisCtx(options),
"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);
}
}
// Convert TDescribeResult to list of strings.
private static List<String> resultToStringList(TDescribeResult result) {
List<String> list = new ArrayList<>();
for (TResultRow row: result.getResults()) {
for (TColumnValue col: row.getColVals()) {
list.add(col.getString_val() == null ? "NULL": col.getString_val().trim());
}
}
return list;
}
private static String selectError(String object) {
return "User '%s' does not have privileges to execute 'SELECT' on: " + object;
}
private static String insertError(String object) {
return "User '%s' does not have privileges to execute 'INSERT' on: " + object;
}
private static String createError(String object) {
return "User '%s' does not have privileges to execute 'CREATE' on: " + object;
}
private static String alterError(String object) {
return "User '%s' does not have privileges to execute 'ALTER' on: " + object;
}
private static String dropError(String object) {
return "User '%s' does not have privileges to execute 'DROP' on: " + object;
}
private static String accessError(String object) {
return "User '%s' does not have privileges to access: " + object;
}
private static String refreshError(String object) {
return "User '%s' does not have privileges to execute " +
"'INVALIDATE METADATA/REFRESH' on: " + object;
}
private static String systemDbError() {
return "Cannot modify system database.";
}
private static String viewDefError(String object) {
return "User '%s' does not have privileges to see the definition of view '" +
object + "'.";
}
private static String createFunctionError(String object) {
return "User '%s' does not have privileges to CREATE functions in: " + object;
}
private static String dropFunctionError(String object) {
return "User '%s' does not have privileges to DROP functions in: " + object;
}
private ScalarFunction addFunction(String db, String fnName, ArrayList<Type> argTypes,
Type retType, String uriPath, String symbolName) {
ScalarFunction fn = ScalarFunction.createForTesting(db, fnName, argTypes, retType,
uriPath, symbolName, null, null, TFunctionBinaryType.NATIVE);
authzCatalog_.addFunction(fn);
return fn;
}
private ScalarFunction addFunction(String db, String fnName) {
return addFunction(db, fnName, new ArrayList<Type>(), Type.INT, "/dummy",
"dummy.class");
}
private void removeFunction(ScalarFunction fn) {
authzCatalog_.removeFunction(fn);
}
private TPrivilegeLevel[] join(TPrivilegeLevel[] level1, TPrivilegeLevel... level2) {
TPrivilegeLevel[] levels = new TPrivilegeLevel[level1.length + level2.length];
int index = 0;
for (TPrivilegeLevel level: level1) {
levels[index++] = level;
}
for (TPrivilegeLevel level: level2) {
levels[index++] = level;
}
return levels;
}
private TPrivilegeLevel[] viewMetadataPrivileges() {
return new TPrivilegeLevel[]{TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
TPrivilegeLevel.SELECT, TPrivilegeLevel.INSERT, TPrivilegeLevel.REFRESH};
}
private static TPrivilegeLevel[] allExcept(TPrivilegeLevel... excludedPrivLevels) {
HashSet<TPrivilegeLevel> excludedSet = Sets.newHashSet(excludedPrivLevels);
List<TPrivilegeLevel> privLevels = new ArrayList<>();
for (TPrivilegeLevel level: TPrivilegeLevel.values()) {
if (!excludedSet.contains(level)) {
privLevels.add(level);
}
}
return privLevels.toArray(new TPrivilegeLevel[0]);
}
private static abstract class WithPrincipal {
protected final AuthzTest test_;
public WithPrincipal(AuthzTest test) { test_ = test; }
public abstract void create(TPrivilege[]... privileges) throws ImpalaException;
public abstract void drop() throws ImpalaException;
public abstract String getName();
}
private static class WithUser extends WithPrincipal {
public WithUser(AuthzTest test) { super(test); }
@Override
public void create(TPrivilege[]... privileges) throws ImpalaException {
test_.createUser(privileges);
}
@Override
public void drop() throws ImpalaException { test_.dropUser(); }
@Override
public String getName() { return test_.user_; }
}
private static class WithRole extends WithPrincipal {
public WithRole(AuthzTest test) { super(test); }
@Override
public void create(TPrivilege[]... privileges) throws ImpalaException {
test_.createRole(privileges);
}
@Override
public void drop() throws ImpalaException { test_.dropRole(); }
@Override
public String getName() { return test_.role_; }
}
private class AuthzTest {
private final AnalysisContext context_;
private final String stmt_;
private final String role_ = "authz_test_role";
private final String user_ = USER.getName();
public AuthzTest(String stmt) {
this(null, stmt);
}
public AuthzTest(AnalysisContext context, String stmt) {
Preconditions.checkNotNull(stmt);
context_ = context;
stmt_ = stmt;
}
private void createRole(TPrivilege[]... privileges) throws ImpalaException {
Role role = authzCatalog_.addRole(role_);
authzCatalog_.addRoleGrantGroup(role_, USER.getName());
for (TPrivilege[] privs: privileges) {
for (TPrivilege privilege: privs) {
privilege.setPrincipal_id(role.getId());
privilege.setPrincipal_type(TPrincipalType.ROLE);
authzCatalog_.addRolePrivilege(role_, privilege);
}
}
}
private void createUser(TPrivilege[]... privileges) throws ImpalaException {
org.apache.impala.catalog.User user = authzCatalog_.addUser(user_);
for (TPrivilege[] privs: privileges) {
for (TPrivilege privilege: privs) {
privilege.setPrincipal_id(user.getId());
privilege.setPrincipal_type(TPrincipalType.USER);
authzCatalog_.addUserPrivilege(user_, privilege);
}
}
}
private void dropRole() throws ImpalaException {
authzCatalog_.removeRole(role_);
}
private void dropUser() throws ImpalaException {
authzCatalog_.removeUser(user_);
}
/**
* This method runs with the specified privileges for the role and then for the user.
*
* A new temporary role/user will be created and assigned to the specified privileges
* into the new role/user. The new role/user will be dropped once this method
* finishes.
*/
public AuthzTest ok(TPrivilege[]... privileges) throws ImpalaException {
for (WithPrincipal withPrincipal: new WithPrincipal[]{
new WithRole(this), new WithUser(this)}) {
try {
withPrincipal.create(privileges);
if (context_ != null) {
authzOk(context_, stmt_, withPrincipal);
} else {
authzOk(stmt_, withPrincipal);
}
} finally {
withPrincipal.drop();
}
}
return this;
}
/**
* This method runs with the specified privileges and checks describe output for the
* role and then the user.
*
* A new temporary role/user will be created and assigned to the specified privileges
* into the new role/user. The new role/user will be dropped once this method
* finishes.
*/
public AuthzTest okDescribe(TTableName table, TDescribeOutputStyle style,
String[] requiredStrings, String[] excludedStrings, TPrivilege[]... privileges)
throws ImpalaException {
for (WithPrincipal withPrincipal: new WithPrincipal[]{
new WithRole(this), new WithUser(this)}) {
try {
withPrincipal.create(privileges);
if (context_ != null) {
authzOk(context_, stmt_, withPrincipal);
} else {
authzOk(stmt_, withPrincipal);
}
List<String> result = resultToStringList(authzFrontend_.describeTable(table,
style, USER));
if (requiredStrings != null) {
for (String str : requiredStrings) {
assertTrue(String.format("\"%s\" is not in the describe output.\n" +
"Expected : %s\n" +
"Actual : %s", str, Arrays.toString(requiredStrings), result),
result.contains(str));
}
}
if (excludedStrings != null) {
for (String str : excludedStrings) {
assertTrue(String.format(
"\"%s\" should not be in the describe output.", str),
!result.contains(str));
}
}
} finally {
withPrincipal.drop();
}
}
return this;
}
/**
* This method runs with the specified privileges for the user and then the role.
*
* A new temporary role/user will be created and assigned to the specified privileges
* into the new role/user. The new role/user will be dropped once this method
* finishes.
*/
public AuthzTest error(String expectedError, TPrivilege[]... privileges)
throws ImpalaException {
for (WithPrincipal withPrincipal: new WithPrincipal[]{
new WithRole(this), new WithUser(this)}) {
try {
withPrincipal.create(privileges);
if (context_ != null) {
authzError(context_, stmt_, expectedError, withPrincipal);
} else {
authzError(stmt_, expectedError, withPrincipal);
}
} finally {
withPrincipal.drop();
}
}
return this;
}
}
private AuthzTest authorize(String stmt) {
return new AuthzTest(stmt);
}
private AuthzTest authorize(AnalysisContext ctx, String stmt) {
return new AuthzTest(ctx, stmt);
}
private TPrivilege[] onServer(TPrivilegeLevel... levels) {
TPrivilege[] privileges = new TPrivilege[levels.length];
for (int i = 0; i < levels.length; i++) {
privileges[i] = new TPrivilege("", levels[i], TPrivilegeScope.SERVER, false);
privileges[i].setServer_name(SENTRY_SERVER);
privileges[i].setPrivilege_name(PrincipalPrivilege.buildPrivilegeName(
privileges[i]));
}
return privileges;
}
private TPrivilege[] onDatabase(String db, TPrivilegeLevel... levels) {
TPrivilege[] privileges = new TPrivilege[levels.length];
for (int i = 0; i < levels.length; i++) {
privileges[i] = new TPrivilege("", levels[i], TPrivilegeScope.DATABASE, false);
privileges[i].setServer_name(SENTRY_SERVER);
privileges[i].setDb_name(db);
privileges[i].setPrivilege_name(PrincipalPrivilege.buildPrivilegeName(
privileges[i]));
}
return privileges;
}
private TPrivilege[] onTable(String db, String table, TPrivilegeLevel... levels) {
TPrivilege[] privileges = new TPrivilege[levels.length];
for (int i = 0; i < levels.length; i++) {
privileges[i] = new TPrivilege("", levels[i], TPrivilegeScope.TABLE, false);
privileges[i].setServer_name(SENTRY_SERVER);
privileges[i].setDb_name(db);
privileges[i].setTable_name(table);
privileges[i].setPrivilege_name(PrincipalPrivilege.buildPrivilegeName(
privileges[i]));
}
return privileges;
}
private TPrivilege[] onColumn(String db, String table, String column,
TPrivilegeLevel... levels) {
return onColumn(db, table, new String[]{column}, levels);
}
private TPrivilege[] onColumn(String db, String table, String[] columns,
TPrivilegeLevel... levels) {
int size = columns.length * levels.length;
TPrivilege[] privileges = new TPrivilege[size];
int idx = 0;
for (int i = 0; i < levels.length; i++) {
for (String column: columns) {
privileges[idx] = new TPrivilege("", levels[i], TPrivilegeScope.COLUMN, false);
privileges[idx].setServer_name(SENTRY_SERVER);
privileges[idx].setDb_name(db);
privileges[idx].setTable_name(table);
privileges[idx].setColumn_name(column);
privileges[idx].setPrivilege_name(PrincipalPrivilege.buildPrivilegeName(
privileges[idx]));
idx++;
}
}
return privileges;
}
private TPrivilege[] onUri(String uri, TPrivilegeLevel... levels) {
TPrivilege[] privileges = new TPrivilege[levels.length];
for (int i = 0; i < levels.length; i++) {
privileges[i] = new TPrivilege("", levels[i], TPrivilegeScope.URI, false);
privileges[i].setServer_name(SENTRY_SERVER);
privileges[i].setUri(uri);
privileges[i].setPrivilege_name(PrincipalPrivilege.buildPrivilegeName(
privileges[i]));
}
return privileges;
}
private void authzOk(String stmt, WithPrincipal withPrincipal) throws ImpalaException {
authzOk(analysisContext_, stmt, withPrincipal);
}
private void authzOk(AnalysisContext context, String stmt, WithPrincipal withPrincipal)
throws ImpalaException {
authzOk(authzFrontend_, context, stmt, withPrincipal);
}
private void authzOk(Frontend fe, AnalysisContext context, String stmt,
WithPrincipal withPrincipal) throws ImpalaException {
try {
parseAndAnalyze(stmt, context, fe);
} catch (AuthorizationException e) {
// Because the same test can be called from multiple statements
// it is useful to know which statement caused the exception.
throw new AuthorizationException(String.format(
"\nPrincipal: %s\nStatement: %s\nError: %s", withPrincipal.getName(),
stmt, e.getMessage(), e));
}
}
/**
* Verifies that a given statement fails authorization and the expected error
* string matches.
*/
private void authzError(String stmt, String expectedError, Matcher matcher,
WithPrincipal withPrincipal) throws ImpalaException {
authzError(analysisContext_, stmt, expectedError, matcher, withPrincipal);
}
private void authzError(String stmt, String expectedError, WithPrincipal withPrincipal)
throws ImpalaException {
authzError(analysisContext_, stmt, expectedError, startsWith(), withPrincipal);
}
private void authzError(AnalysisContext ctx, String stmt, String expectedError,
Matcher matcher, WithPrincipal withPrincipal) throws ImpalaException {
authzError(authzFrontend_, ctx, stmt, expectedError, matcher, withPrincipal);
}
private void authzError(AnalysisContext ctx, String stmt, String expectedError,
WithPrincipal withPrincipal) throws ImpalaException {
authzError(authzFrontend_, ctx, stmt, expectedError, startsWith(), withPrincipal);
}
private interface Matcher {
boolean match(String actual, String expected);
}
private static Matcher exact() {
return new Matcher() {
@Override
public boolean match(String actual, String expected) {
return actual.equals(expected);
}
};
}
private static Matcher startsWith() {
return new Matcher() {
@Override
public boolean match(String actual, String expected) {
return actual.startsWith(expected);
}
};
}
private void authzError(Frontend fe, AnalysisContext ctx, String stmt,
String expectedErrorString, Matcher matcher, WithPrincipal withPrincipal)
throws ImpalaException {
Preconditions.checkNotNull(expectedErrorString);
try {
parseAndAnalyze(stmt, ctx, fe);
} catch (AuthorizationException e) {
// Insert the username into the error.
expectedErrorString = String.format(expectedErrorString, ctx.getUser());
String errorString = e.getMessage();
assertTrue(
"got error:\n" + errorString + "\nexpected:\n" + expectedErrorString,
matcher.match(errorString, expectedErrorString));
return;
}
fail(String.format("Statement did not result in authorization error.\n" +
"Principal: %s\nStatement: %s", withPrincipal.getName(), stmt));
}
private void verifyPrivilegeReqs(String stmt, Set<String> expectedPrivilegeNames)
throws ImpalaException {
verifyPrivilegeReqs(createAnalysisCtx(), stmt, expectedPrivilegeNames);
}
private void verifyPrivilegeReqs(AnalysisContext ctx, String stmt,
Set<String> expectedPrivilegeNames) throws ImpalaException {
AnalysisResult analysisResult = parseAndAnalyze(stmt, ctx, frontend_);
Set<String> actualPrivilegeNames = Sets.newHashSet();
for (PrivilegeRequest privReq: analysisResult.getAnalyzer().getPrivilegeReqs()) {
actualPrivilegeNames.add(privReq.getName());
}
assertEquals(expectedPrivilegeNames, actualPrivilegeNames);
}
}