Skip to content

Commit 5de7450

Browse files
committed
Add authorization support for SHOW CREATE TABLE/VIEW queries
SQL Standard Access Control change is based on this documentation: https://hive.apache.org/docs/latest/sql-standard-based-hive-authorization_40509928/
1 parent e69fe8f commit 5de7450

24 files changed

Lines changed: 193 additions & 1 deletion

File tree

presto-hive/src/main/java/com/facebook/presto/hive/security/LegacyAccessControl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ public Set<String> filterSchemas(ConnectorTransactionHandle transactionHandle, C
102102
return schemaNames;
103103
}
104104

105+
@Override
106+
public void checkCanShowCreateTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName)
107+
{
108+
}
109+
105110
@Override
106111
public void checkCanCreateTable(ConnectorTransactionHandle transaction, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName)
107112
{

presto-hive/src/main/java/com/facebook/presto/hive/security/SqlStandardAccessControl.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import static com.facebook.presto.spi.security.AccessDeniedException.denySetRole;
8484
import static com.facebook.presto.spi.security.AccessDeniedException.denySetTableProperties;
8585
import static com.facebook.presto.spi.security.AccessDeniedException.denyShowColumnsMetadata;
86+
import static com.facebook.presto.spi.security.AccessDeniedException.denyShowCreateTable;
8687
import static com.facebook.presto.spi.security.AccessDeniedException.denyShowRoles;
8788
import static com.facebook.presto.spi.security.AccessDeniedException.denyTruncateTable;
8889
import static com.facebook.presto.spi.security.AccessDeniedException.denyUpdateTableColumns;
@@ -177,6 +178,25 @@ public Set<String> filterSchemas(ConnectorTransactionHandle transactionHandle, C
177178
return schemaNames;
178179
}
179180

181+
@Override
182+
public void checkCanShowCreateTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName)
183+
{
184+
MetastoreContext metastoreContext = new MetastoreContext(
185+
identity, context.getQueryId().getId(),
186+
context.getClientInfo(),
187+
context.getClientTags(),
188+
context.getSource(),
189+
Optional.empty(),
190+
false,
191+
HiveColumnConverterProvider.DEFAULT_COLUMN_CONVERTER_PROVIDER,
192+
context.getWarningCollector(),
193+
context.getRuntimeStats());
194+
195+
if (!checkTablePermission(transactionHandle, identity, metastoreContext, tableName, SELECT, true)) {
196+
denyShowCreateTable(tableName.toString());
197+
}
198+
}
199+
180200
@Override
181201
public void checkCanCreateTable(ConnectorTransactionHandle transaction, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName)
182202
{

presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import static com.facebook.presto.spi.security.AccessDeniedException.denyRenameTable;
6666
import static com.facebook.presto.spi.security.AccessDeniedException.denySelectColumns;
6767
import static com.facebook.presto.spi.security.AccessDeniedException.denyShowColumnsMetadata;
68+
import static com.facebook.presto.spi.security.AccessDeniedException.denyShowCreateTable;
6869
import static com.google.common.base.Suppliers.memoizeWithExpiration;
6970
import static com.google.common.collect.ImmutableSet.toImmutableSet;
7071
import static java.lang.String.format;
@@ -279,6 +280,20 @@ public Set<String> filterSchemas(ConnectorTransactionHandle transactionHandle, C
279280
return allowedSchemas;
280281
}
281282

283+
/**
284+
* Check if identity is allowed to execute SHOW CREATE TABLE or SHOW CREATE VIEW.
285+
*
286+
* @throws AccessDeniedException if not allowed
287+
*/
288+
@Override
289+
public void checkCanShowCreateTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName)
290+
{
291+
if (!checkAccess(identity, tableName, null, HiveAccessType.SELECT)) {
292+
denyShowCreateTable(tableName.getTableName(), format("Access denied - User [ %s ] does not have [SELECT] " +
293+
"privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName()));
294+
}
295+
}
296+
282297
/**
283298
* Check if identity is allowed to create the specified table in this catalog.
284299
*

presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public void testDefaultTableAccessIfNotDefined()
8080
{
8181
ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json");
8282
accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("admin"), CONTEXT, new SchemaTableName("test", "test"));
83+
accessControl.checkCanShowCreateTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("bobschema", "bobtable"));
8384
accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("test", "test"), ImmutableSet.of());
8485
accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("bobschema", "bobtable"), ImmutableSet.of());
8586
accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("admin"), CONTEXT, new SchemaTableName("test", "test"), new SchemaTableName("test1", "test1"));
@@ -93,6 +94,7 @@ public void testTableOperations()
9394
{
9495
ConnectorAccessControl accessControl = createRangerAccessControl("default-schema-level-access.json", "user_groups.json");
9596
// 'etladmin' group have all access {group - etladmin, user - alice}
97+
accessControl.checkCanShowCreateTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"));
9698
accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"));
9799
accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"), new SchemaTableName("foodmart", "test1"));
98100
accessControl.checkCanDropTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"));
@@ -111,6 +113,7 @@ public void testTableOperations()
111113
assertDenied(() -> accessControl.checkCanRenameColumn(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test")));
112114

113115
// Access denied to others {group - readall, user - bob}
116+
assertDenied(() -> accessControl.checkCanShowCreateTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test")));
114117
assertDenied(() -> accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"), ImmutableSet.of(new Subfield("column1"))));
115118
assertDenied(() -> accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test")));
116119
assertDenied(() -> accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"), new SchemaTableName("foodmart", "test1")));

presto-main-base/src/main/java/com/facebook/presto/security/AccessControlManager.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,22 @@ public Set<String> filterSchemas(TransactionId transactionId, Identity identity,
294294
return schemaNames;
295295
}
296296

297+
@Override
298+
public void checkCanShowCreateTable(TransactionId transactionId, Identity identity, AccessControlContext context, QualifiedObjectName tableName)
299+
{
300+
requireNonNull(identity, "identity is null");
301+
requireNonNull(tableName, "tableName is null");
302+
303+
authenticationCheck(() -> checkCanAccessCatalog(identity, context, tableName.getCatalogName()));
304+
305+
authorizationCheck(() -> systemAccessControl.get().checkCanShowCreateTable(identity, context, toCatalogSchemaTableName(tableName)));
306+
307+
CatalogAccessControlEntry entry = getConnectorAccessControl(transactionId, tableName.getCatalogName());
308+
if (entry != null) {
309+
authorizationCheck(() -> entry.getAccessControl().checkCanShowCreateTable(entry.getTransactionHandle(transactionId), identity.toConnectorIdentity(tableName.getCatalogName()), context, toSchemaTableName(tableName)));
310+
}
311+
}
312+
297313
@Override
298314
public void checkCanCreateTable(TransactionId transactionId, Identity identity, AccessControlContext context, QualifiedObjectName tableName)
299315
{

presto-main-base/src/main/java/com/facebook/presto/security/AllowAllSystemAccessControl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ public Set<String> filterSchemas(Identity identity, AccessControlContext context
124124
return schemaNames;
125125
}
126126

127+
@Override
128+
public void checkCanShowCreateTable(Identity identity, AccessControlContext context, CatalogSchemaTableName table)
129+
{
130+
}
131+
127132
@Override
128133
public void checkCanCreateTable(Identity identity, AccessControlContext context, CatalogSchemaTableName table)
129134
{

presto-main-base/src/main/java/com/facebook/presto/security/FileBasedSystemAccessControl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import static com.facebook.presto.spi.security.AccessDeniedException.denyRevokeTablePrivilege;
7676
import static com.facebook.presto.spi.security.AccessDeniedException.denySetTableProperties;
7777
import static com.facebook.presto.spi.security.AccessDeniedException.denySetUser;
78+
import static com.facebook.presto.spi.security.AccessDeniedException.denyShowCreateTable;
7879
import static com.facebook.presto.spi.security.AccessDeniedException.denyTruncateTable;
7980
import static com.facebook.presto.spi.security.AccessDeniedException.denyUpdateTableColumns;
8081
import static com.google.common.base.Preconditions.checkState;
@@ -280,6 +281,14 @@ public Set<String> filterSchemas(Identity identity, AccessControlContext context
280281
return schemaNames;
281282
}
282283

284+
@Override
285+
public void checkCanShowCreateTable(Identity identity, AccessControlContext context, CatalogSchemaTableName table)
286+
{
287+
if (!canAccessCatalog(identity, table.getCatalogName(), ALL)) {
288+
denyShowCreateTable(table.toString());
289+
}
290+
}
291+
283292
@Override
284293
public void checkCanCreateTable(Identity identity, AccessControlContext context, CatalogSchemaTableName table)
285294
{

presto-main-base/src/main/java/com/facebook/presto/security/ReadOnlySystemAccessControl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ public Set<String> filterSchemas(Identity identity, AccessControlContext context
106106
return schemaNames;
107107
}
108108

109+
@Override
110+
public void checkCanShowCreateTable(Identity identity, AccessControlContext context, CatalogSchemaTableName table)
111+
{
112+
}
113+
109114
@Override
110115
public Set<SchemaTableName> filterTables(Identity identity, AccessControlContext context, String catalogName, Set<SchemaTableName> tableNames)
111116
{

presto-main-base/src/main/java/com/facebook/presto/sql/rewrite/ShowQueriesRewrite.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ protected Node visitShowCreate(ShowCreate node, Void context)
502502
}
503503

504504
Query query = parseView(viewDefinition.get().getOriginalSql(), objectName, node);
505+
506+
accessControl.checkCanShowCreateTable(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), objectName);
507+
505508
CreateView.Security security = (viewDefinition.get().isRunAsInvoker()) ? CreateView.Security.INVOKER : CreateView.Security.DEFINER;
506509
String sql = formatSql(new CreateView(createQualifiedName(objectName), query, false, Optional.of(security)), Optional.of(parameters)).trim();
507510
return singleValueQuery("Create View", sql);
@@ -550,6 +553,8 @@ protected Node visitShowCreate(ShowCreate node, Void context)
550553
throw new SemanticException(MISSING_TABLE, node, "Table '%s' does not exist", objectName);
551554
}
552555

556+
accessControl.checkCanShowCreateTable(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), objectName);
557+
553558
ConnectorTableMetadata connectorTableMetadata = metadata.getTableMetadata(session, tableHandle.get()).getMetadata();
554559

555560
Set<String> notNullColumns = connectorTableMetadata.getTableConstraintsHolder().getTableConstraints()

presto-main-base/src/main/java/com/facebook/presto/testing/TestingAccessControlManager.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import static com.facebook.presto.spi.security.AccessDeniedException.denySetSystemSessionProperty;
6363
import static com.facebook.presto.spi.security.AccessDeniedException.denySetTableProperties;
6464
import static com.facebook.presto.spi.security.AccessDeniedException.denySetUser;
65+
import static com.facebook.presto.spi.security.AccessDeniedException.denyShowCreateTable;
6566
import static com.facebook.presto.spi.security.AccessDeniedException.denyTruncateTable;
6667
import static com.facebook.presto.spi.security.AccessDeniedException.denyUpdateTableColumns;
6768
import static com.facebook.presto.testing.TestingAccessControlManager.TestingPrivilegeType.ADD_COLUMN;
@@ -85,6 +86,7 @@
8586
import static com.facebook.presto.testing.TestingAccessControlManager.TestingPrivilegeType.SET_SESSION;
8687
import static com.facebook.presto.testing.TestingAccessControlManager.TestingPrivilegeType.SET_TABLE_PROPERTIES;
8788
import static com.facebook.presto.testing.TestingAccessControlManager.TestingPrivilegeType.SET_USER;
89+
import static com.facebook.presto.testing.TestingAccessControlManager.TestingPrivilegeType.SHOW_CREATE_TABLE;
8890
import static com.facebook.presto.testing.TestingAccessControlManager.TestingPrivilegeType.TRUNCATE_TABLE;
8991
import static com.facebook.presto.testing.TestingAccessControlManager.TestingPrivilegeType.UPDATE_TABLE;
9092
import static com.google.common.base.MoreObjects.toStringHelper;
@@ -182,6 +184,17 @@ public void checkCanRenameSchema(TransactionId transactionId, Identity identity,
182184
}
183185
}
184186

187+
@Override
188+
public void checkCanShowCreateTable(TransactionId transactionId, Identity identity, AccessControlContext context, QualifiedObjectName tableName)
189+
{
190+
if (shouldDenyPrivilege(identity.getUser(), tableName.getObjectName(), SHOW_CREATE_TABLE)) {
191+
denyShowCreateTable(tableName.toString());
192+
}
193+
if (denyPrivileges.isEmpty()) {
194+
super.checkCanShowCreateTable(transactionId, identity, context, tableName);
195+
}
196+
}
197+
185198
@Override
186199
public void checkCanCreateTable(TransactionId transactionId, Identity identity, AccessControlContext context, QualifiedObjectName tableName)
187200
{
@@ -437,7 +450,7 @@ public enum TestingPrivilegeType
437450
{
438451
SET_USER,
439452
CREATE_SCHEMA, DROP_SCHEMA, RENAME_SCHEMA,
440-
CREATE_TABLE, DROP_TABLE, RENAME_TABLE, INSERT_TABLE, DELETE_TABLE, TRUNCATE_TABLE, UPDATE_TABLE,
453+
SHOW_CREATE_TABLE, CREATE_TABLE, DROP_TABLE, RENAME_TABLE, INSERT_TABLE, DELETE_TABLE, TRUNCATE_TABLE, UPDATE_TABLE,
441454
ADD_COLUMN, DROP_COLUMN, RENAME_COLUMN, SELECT_COLUMN,
442455
ADD_CONSTRAINT, DROP_CONSTRAINT,
443456
CREATE_VIEW, RENAME_VIEW, DROP_VIEW, CREATE_VIEW_WITH_SELECT_COLUMNS, SET_TABLE_PROPERTIES,

0 commit comments

Comments
 (0)