Skip to content

Commit

Permalink
Fix listTablePrivileges when owner is not set
Browse files Browse the repository at this point in the history
listTablePrivileges is used internally when altering tables, so must
work even when Hive permission system is not used.
  • Loading branch information
dain committed Nov 22, 2021
1 parent a89d7c1 commit 30c6d91
Show file tree
Hide file tree
Showing 16 changed files with 45 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
delegate.revokeTablePrivileges(databaseName, tableName, tableOwner, grantee, privileges);
}

public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
return delegate.listTablePrivileges(databaseName, tableName, tableOwner, principal);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,10 @@ default void updatePartitionStatistics(HiveIdentity identity, Table table, Strin
void revokeTablePrivileges(String databaseName, String tableName, String tableOwner, HivePrincipal grantee, Set<HivePrivilegeInfo> privileges);

/**
* @param tableOwner
* @param principal when empty, all table privileges are returned
*/
Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal);
Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal);

boolean isImpersonationEnabled();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ public void alterPartition(HiveIdentity identity, String databaseName, String ta
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
return loadValue(
tablePrivilegesCache,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1120,27 +1120,32 @@ public synchronized Set<HivePrivilegeInfo> listTablePrivileges(HiveIdentity iden
SchemaTableName schemaTableName = new SchemaTableName(databaseName, tableName);
Action<TableAndMore> tableAction = tableActions.get(schemaTableName);
if (tableAction == null) {
return delegate.listTablePrivileges(databaseName, tableName, getRequiredTableOwner(identity, databaseName, tableName), principal);
return delegate.listTablePrivileges(databaseName, tableName, getExistingTable(identity, databaseName, tableName).getOwner(), principal);
}
switch (tableAction.getType()) {
case ADD:
case ALTER:
if (principal.isPresent() && principal.get().getType() == PrincipalType.ROLE) {
return ImmutableSet.of();
}
String owner = tableAction.getData().getTable().getOwner().orElseThrow();
if (principal.isPresent() && !principal.get().getName().equals(owner)) {
Optional<String> owner = tableAction.getData().getTable().getOwner();
if (owner.isEmpty()) {
// todo the existing logic below seem off. Only permissions held by the table owner are returned
return ImmutableSet.of();
}
Collection<HivePrivilegeInfo> privileges = tableAction.getData().getPrincipalPrivileges().getUserPrivileges().get(owner);
String ownerUsername = owner.orElseThrow();
if (principal.isPresent() && !principal.get().getName().equals(ownerUsername)) {
return ImmutableSet.of();
}
Collection<HivePrivilegeInfo> privileges = tableAction.getData().getPrincipalPrivileges().getUserPrivileges().get(ownerUsername);
return ImmutableSet.<HivePrivilegeInfo>builder()
.addAll(privileges)
.add(new HivePrivilegeInfo(OWNERSHIP, true, new HivePrincipal(USER, owner), new HivePrincipal(USER, owner)))
.add(new HivePrivilegeInfo(OWNERSHIP, true, new HivePrincipal(USER, ownerUsername), new HivePrincipal(USER, ownerUsername)))
.build();
case INSERT_EXISTING:
case DELETE_ROWS:
case UPDATE:
return delegate.listTablePrivileges(databaseName, tableName, getRequiredTableOwner(identity, databaseName, tableName), principal);
return delegate.listTablePrivileges(databaseName, tableName, getExistingTable(identity, databaseName, tableName).getOwner(), principal);
case DROP:
throw new TableNotFoundException(schemaTableName);
case DROP_PRESERVE_DATA:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ public class UserTableKey
private final Optional<HivePrincipal> principal;
private final String database;
private final String table;
private final String owner;
private final Optional<String> owner;

@JsonCreator
public UserTableKey(
@JsonProperty("principal") Optional<HivePrincipal> principal,
@JsonProperty("database") String database,
@JsonProperty("table") String table,
@JsonProperty("owner") String owner)
@JsonProperty("owner") Optional<String> owner)
{
this.principal = requireNonNull(principal, "principal is null");
this.database = requireNonNull(database, "database is null");
Expand All @@ -64,7 +64,7 @@ public String getTable()
}

@JsonProperty
public String getOwner()
public Optional<String> getOwner()
{
return owner;
}
Expand Down Expand Up @@ -103,7 +103,7 @@ public String toString()
.add("principal", principal)
.add("table", table)
.add("database", database)
.add("owner", owner)
.add("owner", owner.orElse(null))
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
throw new TrinoException(NOT_SUPPORTED, "listTablePrivileges");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -911,12 +911,12 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
private void invalidateTablePrivilegeCacheEntries(String databaseName, String tableName, String tableOwner, HivePrincipal grantee)
{
// some callers of xxxxTablePrivileges use Optional.of(grantee), some Optional.empty() (to get all privileges), so have to invalidate them both
tablePrivilegesCache.invalidate(new UserTableKey(Optional.of(grantee), databaseName, tableName, tableOwner));
tablePrivilegesCache.invalidate(new UserTableKey(Optional.empty(), databaseName, tableName, tableOwner));
tablePrivilegesCache.invalidate(new UserTableKey(Optional.of(grantee), databaseName, tableName, Optional.of(tableOwner)));
tablePrivilegesCache.invalidate(new UserTableKey(Optional.empty(), databaseName, tableName, Optional.of(tableOwner)));
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
return get(tablePrivilegesCache, new UserTableKey(principal, databaseName, tableName, tableOwner));
}
Expand Down Expand Up @@ -968,7 +968,7 @@ public boolean isImpersonationEnabled()
return delegate.isImpersonationEnabled();
}

private Set<HivePrivilegeInfo> loadTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
private Set<HivePrivilegeInfo> loadTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
return delegate.listTablePrivileges(databaseName, tableName, tableOwner, principal);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams;
import io.airlift.json.JsonCodec;
Expand Down Expand Up @@ -1094,16 +1095,15 @@ public synchronized Map<String, Optional<Partition>> getPartitionsByNames(HiveId
}

@Override
public synchronized Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public synchronized Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
Table table = getRequiredTable(databaseName, tableName);
Path permissionsDirectory = getPermissionsDirectory(table);
if (principal.isEmpty()) {
HivePrincipal owner = new HivePrincipal(USER, tableOwner);
return ImmutableSet.<HivePrivilegeInfo>builder()
.addAll(readAllPermissions(permissionsDirectory))
.add(new HivePrivilegeInfo(OWNERSHIP, true, owner, owner))
.build();
Builder<HivePrivilegeInfo> privileges = ImmutableSet.<HivePrivilegeInfo>builder()
.addAll(readAllPermissions(permissionsDirectory));
tableOwner.ifPresent(owner -> privileges.add(new HivePrivilegeInfo(OWNERSHIP, true, new HivePrincipal(USER, owner), new HivePrincipal(USER, owner))));
return privileges.build();
}
ImmutableSet.Builder<HivePrivilegeInfo> result = ImmutableSet.builder();
if (principal.get().getType() == USER && table.getOwner().orElseThrow().equals(principal.get().getName())) {
Expand All @@ -1122,7 +1122,7 @@ public synchronized void grantTablePrivileges(String databaseName, String tableN
@Override
public synchronized void revokeTablePrivileges(String databaseName, String tableName, String tableOwner, HivePrincipal grantee, Set<HivePrivilegeInfo> privileges)
{
Set<HivePrivilegeInfo> currentPrivileges = listTablePrivileges(databaseName, tableName, tableOwner, Optional.of(grantee));
Set<HivePrivilegeInfo> currentPrivileges = listTablePrivileges(databaseName, tableName, Optional.of(tableOwner), Optional.of(grantee));
Set<HivePrivilegeInfo> privilegesToRemove = privileges.stream()
.map(p -> new HivePrivilegeInfo(p.getHivePrivilege(), p.isGrantOption(), p.getGrantor(), grantee))
.collect(toImmutableSet());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
return ImmutableSet.of();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
return delegate.listTablePrivileges(databaseName, tableName, tableOwner, principal);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1452,7 +1452,7 @@ public void grantTablePrivileges(String databaseName, String tableName, String t
.stopOnIllegalExceptions()
.run("grantTablePrivileges", stats.getGrantTablePrivileges().wrap(() -> {
try (ThriftMetastoreClient metastoreClient = createMetastoreClient()) {
Set<HivePrivilegeInfo> existingPrivileges = listTablePrivileges(databaseName, tableName, tableOwner, Optional.of(grantee));
Set<HivePrivilegeInfo> existingPrivileges = listTablePrivileges(databaseName, tableName, Optional.of(tableOwner), Optional.of(grantee));

Set<PrivilegeGrantInfo> privilegesToGrant = new HashSet<>(requestedPrivileges);
Iterator<PrivilegeGrantInfo> iterator = privilegesToGrant.iterator();
Expand Down Expand Up @@ -1503,7 +1503,7 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
.stopOnIllegalExceptions()
.run("revokeTablePrivileges", stats.getRevokeTablePrivileges().wrap(() -> {
try (ThriftMetastoreClient metastoreClient = createMetastoreClient()) {
Set<HivePrivilege> existingHivePrivileges = listTablePrivileges(databaseName, tableName, tableOwner, Optional.of(grantee)).stream()
Set<HivePrivilege> existingHivePrivileges = listTablePrivileges(databaseName, tableName, Optional.of(tableOwner), Optional.of(grantee)).stream()
.map(HivePrivilegeInfo::getHivePrivilege)
.collect(toImmutableSet());

Expand All @@ -1529,7 +1529,7 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
try {
return retry()
Expand All @@ -1539,15 +1539,14 @@ public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String ta
ImmutableSet.Builder<HivePrivilegeInfo> privileges = ImmutableSet.builder();
List<HiveObjectPrivilege> hiveObjectPrivilegeList;
if (principal.isEmpty()) {
HivePrincipal ownerPrincipal = new HivePrincipal(USER, tableOwner);
privileges.add(new HivePrivilegeInfo(OWNERSHIP, true, ownerPrincipal, ownerPrincipal));
tableOwner.ifPresent(owner -> privileges.add(new HivePrivilegeInfo(OWNERSHIP, true, new HivePrincipal(USER, owner), new HivePrincipal(USER, owner))));
hiveObjectPrivilegeList = client.listPrivileges(
null,
null,
new HiveObjectRef(TABLE, databaseName, tableName, null, null));
}
else {
if (principal.get().getType() == USER && tableOwner.equals(principal.get().getName())) {
if (tableOwner.isPresent() && principal.get().getType() == USER && tableOwner.get().equals(principal.get().getName())) {
privileges.add(new HivePrivilegeInfo(OWNERSHIP, true, principal.get(), principal.get()));
}
hiveObjectPrivilegeList = client.listPrivileges(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,10 @@ public interface ThriftMetastore
void revokeTablePrivileges(String databaseName, String tableName, String tableOwner, HivePrincipal grantee, Set<HivePrivilegeInfo> privileges);

/**
* @param tableOwner
* @param principal when empty, all table privileges are returned
*/
Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal);
Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal);

boolean isImpersonationEnabled();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private void validateMetadata(HiveMetastore hiveMetastore)
assertEquals(hiveMetastore.getPartitionNamesByFilter(HIVE_CONTEXT, "database", "table", PARTITION_COLUMN_NAMES, TupleDomain.all()), Optional.of(ImmutableList.of("value")));
assertEquals(hiveMetastore.getPartitionNamesByFilter(HIVE_CONTEXT, "database", "table", PARTITION_COLUMN_NAMES, TUPLE_DOMAIN), Optional.of(ImmutableList.of("value")));
assertEquals(hiveMetastore.getPartitionsByNames(HIVE_CONTEXT, TABLE, ImmutableList.of("value")), ImmutableMap.of("value", Optional.of(PARTITION)));
assertEquals(hiveMetastore.listTablePrivileges("database", "table", "owner", Optional.of(new HivePrincipal(USER, "user"))), ImmutableSet.of(PRIVILEGE_INFO));
assertEquals(hiveMetastore.listTablePrivileges("database", "table", Optional.of("owner"), Optional.of(new HivePrincipal(USER, "user"))), ImmutableSet.of(PRIVILEGE_INFO));
assertEquals(hiveMetastore.listRoles(), ImmutableSet.of("role"));
assertEquals(hiveMetastore.listRoleGrants(new HivePrincipal(USER, "user")), ImmutableSet.of(ROLE_GRANT));
assertEquals(hiveMetastore.listGrantedPrincipals("role"), ImmutableSet.of(ROLE_GRANT));
Expand Down Expand Up @@ -301,7 +301,7 @@ public Map<String, Optional<Partition>> getPartitionsByNames(HiveIdentity identi
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
if (databaseName.equals("database") && tableName.equals("table") && principal.get().getType() == USER && principal.get().getName().equals("user")) {
return ImmutableSet.of(PRIVILEGE_INFO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public void alterPartition(HiveIdentity identity, String databaseName, String ta
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> prestoPrincipal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> prestoPrincipal)
{
throw new UnsupportedOperationException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ public Set<RoleGrant> listRoleGrants(HivePrincipal principal)
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
return ImmutableSet.of();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public void revokeTablePrivileges(String databaseName, String tableName, String
}

@Override
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, String tableOwner, Optional<HivePrincipal> principal)
public Set<HivePrivilegeInfo> listTablePrivileges(String databaseName, String tableName, Optional<String> tableOwner, Optional<HivePrincipal> principal)
{
throw new UnsupportedOperationException();
}
Expand Down

0 comments on commit 30c6d91

Please sign in to comment.