Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Support role management #7346

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
1839203
Add syntax support for SHOW GRANTS
Sep 13, 2016
90718e9
Add PrivilegeInfo class to SPI
Sep 27, 2016
0fcd676
Make metadata changes for SHOW GRANTS
Oct 14, 2016
5b4a37e
Implement SHOW GRANTS for Hive connector
Oct 14, 2016
e89bdca
Add table in INFORMATION_SCHEMA to store table privileges
Oct 14, 2016
249eba1
Rewrite SHOW GRANTS as a SELECT query
Oct 14, 2016
8aa7d34
Add product tests for SHOW GRANTS
Oct 19, 2016
73bc07e
Document SHOW GRANTS
Nov 22, 2016
ed7fe4b
Add access control for SHOW GRANTS
Feb 23, 2017
32bfd18
Introduce CREATE ROLE and DROP ROLE statements
Feb 8, 2017
ddc52cf
Move PrincipalType to presto-spi
Feb 16, 2017
2508566
Expose Create/Drop/List roles methods in SPI
Feb 9, 2017
010ac43
Introduce <catalog>.information_schema.roles table
Feb 22, 2017
fdf530f
Remove unused InMemoryHiveMetastore
Feb 9, 2017
7cdb994
Assign admin role to subset of users in FileHiveMetastore
Mar 2, 2017
b882f1b
Speedup TestHiveFileBasedSecurity
Mar 2, 2017
515cb79
Implement Create/Drop/List roles in Hive connector
Feb 10, 2017
4b86875
Introduce GRANT/REVOKE roles statements
Feb 21, 2017
c396608
Add Grant/Revoke/List roles authorization to the SPI
Feb 21, 2017
f1909cd
Introduce APPLICABLE_ROLES view
Feb 22, 2017
682ba55
Implement Grant/Revoke/ListApplicableRoles in Hive
Mar 2, 2017
73e563a
Refactor GRANT/REVOKE in Hive
Feb 23, 2017
bcd2424
Introduce access control for GRANT/REVOKE ROLE
Feb 23, 2017
be8565f
Prepare metastore interface to accept ROLE for GRANT/REVOKE
Mar 2, 2017
0c35d15
Introduce SET ROLE statement
Feb 24, 2017
9e95e0f
Introduce ConnectorIdentity
Mar 10, 2017
1611266
Implement SET ROLE
Feb 24, 2017
d18f22d
Store catalog selected roles in Identity
Mar 10, 2017
411ebde
Introduce ENABLED_ROLES view
Feb 25, 2017
4b88b58
Implement SET ROLE in Hive Connector
Feb 25, 2017
6c490ba
Accept ROLE in GRANT/REVOKE Privileges statements
Mar 8, 2017
ecfbb4c
Add SHOW ROLES to the parser
cawallin Mar 10, 2017
d2fda35
Rewrite SHOW ROLES as a select query
cawallin Mar 10, 2017
2acf38d
Add access control checks for SHOW ROLES
cawallin Mar 10, 2017
323b57b
Add docs for SHOW ROLES
cawallin Mar 10, 2017
66ff09e
Product tests for SHOW ROLES
cawallin Mar 13, 2017
acabc65
Add SHOW CURRENT ROLES
cawallin Mar 13, 2017
6a246e9
Add SHOW ROLE GRANTS syntax
cawallin Mar 13, 2017
06a9042
Add listRoleGrants to the SPI
cawallin Mar 14, 2017
6969228
Implement listRoleGrants() in Hive
cawallin Mar 14, 2017
02d9fbd
Implement SHOW ROLE GRANTS rewrite
cawallin Mar 14, 2017
7668f79
Add docs for SHOW ROLE GRANTS
cawallin Mar 14, 2017
852d7cd
Access control for SHOW ROLE GRANTS and SHOW CURRENT ROLES
cawallin Mar 15, 2017
c4afa44
Remove redundant checkDatabasePermission methods
Mar 9, 2017
79946ef
Reorder methods in SqlStandardAccessControl
Mar 9, 2017
d3a9ae0
Rename getGrantOptionForPrivilege to hasGrantOptionForPrivilege
Mar 9, 2017
e16aaf1
Remove hive privilege null check
Mar 9, 2017
78bb8da
Allow all for admin role
Mar 9, 2017
187af6e
Introduce isTableOwner method for readability
Mar 9, 2017
567ffe1
Simplify checkTablePermission
Mar 9, 2017
40467a8
Refactor canCreateView security checks
Mar 9, 2017
5e2cb1f
Consider enabled roles for permissions
Mar 10, 2017
39a9298
Refactor HivePrivilegeInfo
Mar 13, 2017
bb4a0e0
Reorder methods in HivePrivilegeInfo
Mar 13, 2017
b92e79c
Move parsePrivilege to MetastoreUtil
Mar 13, 2017
7a9775f
Add grantor to HivePrivilegeInfo
Mar 13, 2017
9e0a23d
Add grantor_type and grantee_type columns to table_privileges
Mar 13, 2017
9b62dac
More product tests for SET ROLE
Mar 13, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions presto-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
<artifactId>presto-client</artifactId>
</dependency>

<dependency>
<groupId>com.facebook.presto</groupId>
<artifactId>presto-spi</artifactId>
</dependency>

<dependency>
<groupId>com.facebook.presto</groupId>
<artifactId>presto-parser</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import com.facebook.presto.cli.ClientOptions.OutputFormat;
import com.facebook.presto.client.ClientSession;
import com.facebook.presto.spi.security.SelectedRole;
import com.facebook.presto.sql.parser.IdentifierSymbol;
import com.facebook.presto.sql.parser.ParsingException;
import com.facebook.presto.sql.parser.SqlParser;
Expand Down Expand Up @@ -55,6 +56,7 @@
import static com.facebook.presto.client.ClientSession.withCatalogAndSchema;
import static com.facebook.presto.client.ClientSession.withPreparedStatements;
import static com.facebook.presto.client.ClientSession.withProperties;
import static com.facebook.presto.client.ClientSession.withRoles;
import static com.facebook.presto.client.ClientSession.withTransactionId;
import static com.facebook.presto.sql.parser.StatementSplitter.Statement;
import static com.facebook.presto.sql.parser.StatementSplitter.isEmptyStatement;
Expand Down Expand Up @@ -327,6 +329,13 @@ private static void process(QueryRunner queryRunner, String sql, OutputFormat ou
session = withProperties(session, sessionProperties);
}

// update session roles
if (!query.getSetRoles().isEmpty()) {
Map<String, SelectedRole> roles = new HashMap<>(session.getRoles());
roles.putAll(query.getSetRoles());
session = withRoles(session, roles);
}

// update prepared statements if present
if (!query.getAddedPreparedStatements().isEmpty() || !query.getDeallocatedPreparedStatements().isEmpty()) {
Map<String, String> preparedStatements = new HashMap<>(session.getPreparedStatements());
Expand Down
6 changes: 6 additions & 0 deletions presto-cli/src/main/java/com/facebook/presto/cli/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.facebook.presto.client.QueryError;
import com.facebook.presto.client.QueryResults;
import com.facebook.presto.client.StatementClient;
import com.facebook.presto.spi.security.SelectedRole;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
Expand Down Expand Up @@ -72,6 +73,11 @@ public Set<String> getResetSessionProperties()
return client.getResetSessionProperties();
}

public Map<String, SelectedRole> getSetRoles()
{
return client.getSetRoles();
}

public Map<String, String> getAddedPreparedStatements()
{
return client.getAddedPreparedStatements();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/
package com.facebook.presto.client;

import com.facebook.presto.spi.security.SelectedRole;
import com.facebook.presto.spi.type.TimeZoneKey;
import com.google.common.collect.ImmutableMap;
import io.airlift.units.Duration;
Expand Down Expand Up @@ -41,6 +42,7 @@ public class ClientSession
private final Locale locale;
private final Map<String, String> properties;
private final Map<String, String> preparedStatements;
private final Map<String, SelectedRole> roles;
private final String transactionId;
private final boolean debug;
private final Duration clientRequestTimeout;
Expand All @@ -58,6 +60,7 @@ public static ClientSession withCatalogAndSchema(ClientSession session, String c
session.getLocale(),
session.getProperties(),
session.getPreparedStatements(),
session.getRoles(),
session.getTransactionId(),
session.isDebug(),
session.getClientRequestTimeout());
Expand All @@ -76,6 +79,26 @@ public static ClientSession withProperties(ClientSession session, Map<String, St
session.getLocale(),
properties,
session.getPreparedStatements(),
session.getRoles(),
session.getTransactionId(),
session.isDebug(),
session.getClientRequestTimeout());
}

public static ClientSession withRoles(ClientSession session, Map<String, SelectedRole> roles)
{
return new ClientSession(
session.getServer(),
session.getUser(),
session.getSource(),
session.getClientInfo(),
session.getCatalog(),
session.getSchema(),
session.getTimeZone().getId(),
session.getLocale(),
session.getProperties(),
session.getPreparedStatements(),
roles,
session.getTransactionId(),
session.isDebug(),
session.getClientRequestTimeout());
Expand All @@ -94,6 +117,7 @@ public static ClientSession withPreparedStatements(ClientSession session, Map<St
session.getLocale(),
session.getProperties(),
preparedStatements,
session.getRoles(),
session.getTransactionId(),
session.isDebug(),
session.getClientRequestTimeout());
Expand All @@ -112,6 +136,7 @@ public static ClientSession withTransactionId(ClientSession session, String tran
session.getLocale(),
session.getProperties(),
session.getPreparedStatements(),
session.getRoles(),
transactionId,
session.isDebug(),
session.getClientRequestTimeout());
Expand All @@ -130,6 +155,7 @@ public static ClientSession stripTransactionId(ClientSession session)
session.getLocale(),
session.getProperties(),
session.getPreparedStatements(),
session.getRoles(),
null,
session.isDebug(),
session.getClientRequestTimeout());
Expand Down Expand Up @@ -166,6 +192,25 @@ public ClientSession(
String transactionId,
boolean debug,
Duration clientRequestTimeout)
{
this(server, user, source, clientInfo, catalog, schema, timeZoneId, locale, properties, preparedStatements, emptyMap(), transactionId, debug, clientRequestTimeout);
}

public ClientSession(
URI server,
String user,
String source,
String clientInfo,
String catalog,
String schema,
String timeZoneId,
Locale locale,
Map<String, String> properties,
Map<String, String> preparedStatements,
Map<String, SelectedRole> roles,
String transactionId,
boolean debug,
Duration clientRequestTimeout)
{
this.server = requireNonNull(server, "server is null");
this.user = user;
Expand All @@ -179,6 +224,7 @@ public ClientSession(
this.debug = debug;
this.properties = ImmutableMap.copyOf(requireNonNull(properties, "properties is null"));
this.preparedStatements = ImmutableMap.copyOf(requireNonNull(preparedStatements, "preparedStatements is null"));
this.roles = ImmutableMap.copyOf(requireNonNull(roles, "roles is null"));
this.clientRequestTimeout = clientRequestTimeout;

// verify the properties are valid
Expand Down Expand Up @@ -241,6 +287,14 @@ public Map<String, String> getPreparedStatements()
return preparedStatements;
}

/**
* Returns the map of catalog name -> selected role
*/
public Map<String, SelectedRole> getRoles()
{
return roles;
}

public String getTransactionId()
{
return transactionId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public final class PrestoHeaders
public static final String PRESTO_SESSION = "X-Presto-Session";
public static final String PRESTO_SET_SESSION = "X-Presto-Set-Session";
public static final String PRESTO_CLEAR_SESSION = "X-Presto-Clear-Session";
public static final String PRESTO_SET_ROLE = "X-Presto-Set-Role";
public static final String PRESTO_ROLE = "X-Presto-Role";
public static final String PRESTO_PREPARED_STATEMENT = "X-Presto-Prepared-Statement";
public static final String PRESTO_ADDED_PREPARE = "X-Presto-Added-Prepare";
public static final String PRESTO_DEALLOCATED_PREPARE = "X-Presto-Deallocated-Prepare";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/
package com.facebook.presto.client;

import com.facebook.presto.spi.security.SelectedRole;
import com.facebook.presto.spi.type.TimeZoneKey;
import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
Expand Down Expand Up @@ -48,6 +49,7 @@
import static com.facebook.presto.client.PrestoHeaders.PRESTO_CLEAR_SESSION;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_CLEAR_TRANSACTION_ID;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_DEALLOCATED_PREPARE;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_SET_ROLE;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_SET_SESSION;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_STARTED_TRANSACTION_ID;
import static com.google.common.base.MoreObjects.firstNonNull;
Expand Down Expand Up @@ -86,6 +88,7 @@ public class StatementClient
private final AtomicReference<QueryResults> currentResults = new AtomicReference<>();
private final Map<String, String> setSessionProperties = new ConcurrentHashMap<>();
private final Set<String> resetSessionProperties = Sets.newConcurrentHashSet();
private final Map<String, SelectedRole> setRoles = new ConcurrentHashMap<>();
private final Map<String, String> addedPreparedStatements = new ConcurrentHashMap<>();
private final Set<String> deallocatedPreparedStatements = Sets.newConcurrentHashSet();
private final AtomicReference<String> startedtransactionId = new AtomicReference<>();
Expand Down Expand Up @@ -149,6 +152,11 @@ private Request buildQueryRequest(ClientSession session, String query)
builder.addHeader(PrestoHeaders.PRESTO_SESSION, entry.getKey() + "=" + entry.getValue());
}

Map<String, SelectedRole> roles = session.getRoles();
for (Entry<String, SelectedRole> entry : roles.entrySet()) {
builder.addHeader(PrestoHeaders.PRESTO_ROLE, entry.getKey() + '=' + urlEncode(entry.getValue().toString()));
}

Map<String, String> statements = session.getPreparedStatements();
for (Entry<String, String> entry : statements.entrySet()) {
builder.addHeader(PrestoHeaders.PRESTO_PREPARED_STATEMENT, urlEncode(entry.getKey()) + "=" + urlEncode(entry.getValue()));
Expand Down Expand Up @@ -216,6 +224,11 @@ public Set<String> getResetSessionProperties()
return ImmutableSet.copyOf(resetSessionProperties);
}

public Map<String, SelectedRole> getSetRoles()
{
return ImmutableMap.copyOf(setRoles);
}

public Map<String, String> getAddedPreparedStatements()
{
return ImmutableMap.copyOf(addedPreparedStatements);
Expand Down Expand Up @@ -319,6 +332,14 @@ private void processResponse(JsonResponse<QueryResults> response)
resetSessionProperties.add(clearSession);
}

for (String setRole : response.getHeaders(PRESTO_SET_ROLE)) {
List<String> keyValue = SESSION_HEADER_SPLITTER.splitToList(setRole);
if (keyValue.size() != 2) {
continue;
}
setRoles.put(keyValue.get(0), SelectedRole.valueOf(urlDecode(keyValue.get(1))));
}

for (String entry : response.getHeaders(PRESTO_ADDED_PREPARE)) {
List<String> keyValue = SESSION_HEADER_SPLITTER.splitToList(entry);
if (keyValue.size() != 2) {
Expand Down
3 changes: 3 additions & 0 deletions presto-docs/src/main/sphinx/connector/mysql.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ The following SQL statements are not yet supported:
* :doc:`/sql/create-table` (:doc:`/sql/create-table-as` is supported)
* :doc:`/sql/grant`
* :doc:`/sql/revoke`
* :doc:`/sql/show-grants`
* :doc:`/sql/show-roles`
* :doc:`/sql/show-role-grants`
3 changes: 3 additions & 0 deletions presto-docs/src/main/sphinx/connector/postgresql.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,6 @@ The following SQL statements are not yet supported:
* :doc:`/sql/create-table` (:doc:`/sql/create-table-as` is supported)
* :doc:`/sql/grant`
* :doc:`/sql/revoke`
* :doc:`/sql/show-grants`
* :doc:`/sql/show-roles`
* :doc:`/sql/show-role-grants`
3 changes: 3 additions & 0 deletions presto-docs/src/main/sphinx/sql.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ This chapter describes the SQL syntax used in Presto.
sql/show-create-table
sql/show-create-view
sql/show-functions
sql/show-grants
sql/show-partitions
sql/show-role-grants
sql/show-roles
sql/show-schemas
sql/show-session
sql/show-tables
Expand Down
7 changes: 3 additions & 4 deletions presto-docs/src/main/sphinx/sql/grant.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ Synopsis
.. code-block:: none

GRANT ( privilege [, ...] | ( ALL PRIVILEGES ) )
ON [ TABLE ] table_name TO ( grantee | PUBLIC )
ON [ TABLE ] table_name TO ( user | USER user | ROLE role )
[ WITH GRANT OPTION ]

Usage of the term ``grantee`` denotes both users and roles.

Description
-----------

Expand All @@ -39,7 +37,7 @@ Grant ``SELECT`` privilege on the table ``nation`` to user ``alice``, additional

Grant ``SELECT`` privilege on the table ``orders`` to everyone::

GRANT SELECT ON orders TO PUBLIC;
GRANT SELECT ON orders TO ROLE PUBLIC;

Limitations
-----------
Expand All @@ -51,3 +49,4 @@ See Also
--------

:doc:`revoke`
:doc:`show-grants`
7 changes: 3 additions & 4 deletions presto-docs/src/main/sphinx/sql/revoke.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ Synopsis

REVOKE [ GRANT OPTION FOR ]
( privilege [, ...] | ALL PRIVILEGES )
ON [ TABLE ] table_name FROM ( grantee | PUBLIC )

Usage of the term ``grantee`` denotes both users and roles.
ON [ TABLE ] table_name FROM ( user | USER user | ROLE role )

Description
-----------
Expand All @@ -35,7 +33,7 @@ Revoke ``INSERT`` and ``SELECT`` privileges on the table ``orders`` from user ``

Revoke ``SELECT`` privilege on the table ``nation`` from everyone, additionally revoking the privilege to grant ``SELECT`` privilege::

REVOKE GRANT OPTION FOR SELECT ON nation FROM PUBLIC;
REVOKE GRANT OPTION FOR SELECT ON nation FROM ROLE PUBLIC;

Revoke all privileges on the table ``test`` from user ``alice``::

Expand All @@ -51,3 +49,4 @@ See Also
--------

:doc:`grant`
:doc:`show-grants`
46 changes: 46 additions & 0 deletions presto-docs/src/main/sphinx/sql/show-grants.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
===========
SHOW GRANTS
===========

Synopsis
--------

.. code-block:: none

SHOW GRANTS ON ( [ TABLE ] table_name | ALL )

Description
-----------

List the grants for the current user on the specified table in the current catalog.

Specifying ``ALL`` lists the grants for the current user on all the tables in all the schemas in the current catalog.

The command requires the current catalog to be set.

.. note::

Ensure that authentication has been enabled before running any of the authorization commands.

Examples
--------

List the grants for the current user on table ``orders``::

SHOW GRANTS ON TABLE ``orders``

List the grants for the current user on all the tables in all the schemas in the current catalog::

SHOW GRANTS ON ALL;

Limitations
-----------

Some connectors have no support for ``SHOW GRANTS``.
See connector documentation for more details.

See Also
--------

:doc:`grant`
:doc:`revoke`
Loading