From 142cdaa5bf03c1019aaa542b9b3b9a139a022443 Mon Sep 17 00:00:00 2001 From: Ashish Tadose Date: Mon, 14 Dec 2020 19:12:41 +0530 Subject: [PATCH 1/5] Hive Ranger security plugin --- .../main/sphinx/connector/hive-security.rst | 85 ++ presto-hive/pom.xml | 76 ++ .../hive/security/HiveSecurityModule.java | 2 + .../security/ranger/RangerAuthorizer.java | 112 +++ .../ranger/RangerBasedAccessControl.java | 493 +++++++++++ .../RangerBasedAccessControlConfig.java | 105 +++ .../RangerBasedAccessControlModule.java | 54 ++ .../presto/hive/security/ranger/Users.java | 120 +++ .../presto/hive/security/ranger/VXUser.java | 180 +++++ .../ranger/TestRangerBasedAccessControl.java | 183 +++++ .../TestRangerBasedAccessControlConfig.java | 118 +++ .../default-allow-all.json | 564 +++++++++++++ .../default-schema-level-access.json | 748 +++++++++++++++++ .../default-table-column-access.json | 723 +++++++++++++++++ .../default-table-select-update.json | 762 ++++++++++++++++++ .../user_groups.json | 87 ++ 16 files changed, 4412 insertions(+) create mode 100644 presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java create mode 100644 presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java create mode 100644 presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java create mode 100644 presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlModule.java create mode 100644 presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/Users.java create mode 100644 presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/VXUser.java create mode 100644 presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java create mode 100644 presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java create mode 100644 presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-allow-all.json create mode 100644 presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-schema-level-access.json create mode 100644 presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-column-access.json create mode 100644 presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-select-update.json create mode 100644 presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json diff --git a/presto-docs/src/main/sphinx/connector/hive-security.rst b/presto-docs/src/main/sphinx/connector/hive-security.rst index fa4340a5f850b..9bfa8db2ccf17 100644 --- a/presto-docs/src/main/sphinx/connector/hive-security.rst +++ b/presto-docs/src/main/sphinx/connector/hive-security.rst @@ -39,6 +39,10 @@ Property Value Description To alter these privileges, use the :doc:`/sql/grant` and :doc:`/sql/revoke` commands. See :ref:`hive-sql-standard-based-authorization` for details. + +``ranger`` Users are permitted to perform the operations as per the + authorization policies configured in Ranger Hive service. + See :ref:`hive-ranger-based-authorization` for details. ================================================== ============================================================ .. _hive-sql-standard-based-authorization: @@ -522,6 +526,87 @@ See below for an example. ] } +.. _hive-ranger-based-authorization: + +Ranger Based Authorization +========================== + +Apache Ranger is a widely used framework for providing centralized security +administration and management. +Ranger supports various components plugin to allow authorization policy +management and verification by integrating with components. +Ranger Hive plugin is used to extend authorization for Hive clients such as +Beeline. +Presto ranger plugin for Hive connector can be integrated with Ranger +as a access control system to perform authorization for presto hive connector +queries configure with polices defined Ranger Hive component . When a query is +submitted to Presto, Presto parses and analyzes the query to understand the +privileges required by the user to access objects such as schemas and tables. +Once a list of these objects is created, Presto communicates with the Ranger +service to determine if the request is valid. If the request is valid, the +query continues to execute. If the request is invalid, because the user does +not have the necessary privileges to query an object, an error is returned. +Ranger policies are cached in Presto to improve performance. + +Authentication is handled outside of Ranger, for example using LDAP, and +Ranger uses the authenticated user and user groups to associate with the +policy definition. + +Requirements +------------ + +Before you configure Presto for any integration with Apache Ranger, +verify the following prerequisites: + +Presto coordinator and workers have the appropriate network access to +communicate with the Ranger service. Typically this is port 6080. + +Apache Ranger 0.7.0 or higher must be used + +Policies +-------- + +A policy is a combination of set of resources and the associated privileges. +Ranger provides a user interface, or optionally a REST API, to create +and manage these access control policies. + +Users, groups, and roles +------------------------ + +Apache Ranger has UserGroups sync mechanism by which Users, groups, and +roles are sourced from your configured authentication system with Apache +Ranger. + +Supported authorizations +------------------------ + +Ranger Hive service allows to configure privileges at schema, table, column +level. Note to restrict access to specific user and groups ranger policies +needs to configure with explict deny conditions. + +Access for listing schema, show tables metadata & configuring session +properties are enabled by default. + +Configuration properties +------------------------ + +================================================== ============================================================ ============ +Property Name Description Default +================================================== ============================================================ ============ +``hive.ranger.rest-endpoint`` URL address of the Ranger REST service. Kerberos + authentication is not supported yet. + +``hive.ranger.refresh-policy-period`` Interval at which cached policies are refreshed 60s + +``hive.ranger.policy.hive-servicename`` Ranger Hive plugin service name + +``hive.ranger.service.basic-auth-username`` Ranger Hive plugin username configured with + for Basic HTTP auth. + +``hive.ranger.service.basic-auth-password`` Ranger Hive plugin password configured with + for Basic HTTP auth. +================================================== ============================================================ ============ + HDFS wire encryption -------------------- diff --git a/presto-hive/pom.xml b/presto-hive/pom.xml index 85d79c5158ce3..66a7b4ef99b93 100644 --- a/presto-hive/pom.xml +++ b/presto-hive/pom.xml @@ -79,6 +79,11 @@ provided + + com.facebook.presto + presto-client + + com.facebook.presto.hive hive-apache @@ -246,6 +251,77 @@ zstd-jni + + org.apache.ranger + ranger-plugins-common + 0.7.1 + + + log4j + log4j + + + commons-beanutils + commons-beanutils-core + + + org.apache.hadoop + hadoop-common + + + kafka_2.10 + org.apache.kafka + + + jersey-bundle + com.sun.jersey + + + commons-logging + commons-logging + + + commons-logging + commons-logging-api + + + org.codehaus.jackson + jackson-jaxrs + + + org.eclipse.persistence + eclipselink + + + org.apache.solr + solr-solrj + + + org.eclipse.persistence + javax.persistence + + + + + + com.squareup.okhttp3 + okhttp + + + + + commons-lang + commons-lang + 2.6 + runtime + + + commons-collections + commons-collections + 3.2.2 + runtime + + com.facebook.airlift diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/HiveSecurityModule.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/HiveSecurityModule.java index 17824d6f22ddd..617bd93367d03 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/HiveSecurityModule.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/HiveSecurityModule.java @@ -14,6 +14,7 @@ package com.facebook.presto.hive.security; import com.facebook.airlift.configuration.AbstractConfigurationAwareModule; +import com.facebook.presto.hive.security.ranger.RangerBasedAccessControlModule; import com.facebook.presto.plugin.base.security.FileBasedAccessControlModule; import com.facebook.presto.plugin.base.security.ReadOnlySecurityModule; import com.google.inject.Binder; @@ -31,6 +32,7 @@ protected void setup(Binder binder) bindSecurityModule("file", new FileBasedAccessControlModule()); bindSecurityModule("read-only", new ReadOnlySecurityModule()); bindSecurityModule("sql-standard", new SqlStandardSecurityModule()); + bindSecurityModule("ranger", new RangerBasedAccessControlModule()); } private void bindSecurityModule(String name, Module module) diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java new file mode 100644 index 0000000000000..9c33933f1a67f --- /dev/null +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java @@ -0,0 +1,112 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.amazonaws.util.StringUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.Credentials; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; +import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl; +import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl; +import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.service.RangerBasePlugin; +import org.apache.ranger.plugin.util.ServicePolicies; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Set; + +import static com.google.common.net.HttpHeaders.AUTHORIZATION; +import static java.util.Objects.requireNonNull; + +public class RangerAuthorizer +{ + private static volatile RangerBasePlugin plugin; + + public RangerAuthorizer(ServicePolicies servicePolicies) + { + plugin = new RangerBasePlugin("hive", "standalone-hive"); + plugin.setResultProcessor(null); + plugin.setPolicies(servicePolicies); + } + + private static T jsonParse(Response response, Class clazz) + throws IOException + { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.body().byteStream())); + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(bufferedReader, clazz); + } + + public static Interceptor basicAuth(String user, String password) + { + requireNonNull(user, "user is null"); + requireNonNull(password, "password is null"); + + String credential = Credentials.basic(user, password); + return chain -> chain.proceed(chain.request().newBuilder() + .header(AUTHORIZATION, credential) + .build()); + } + + private static OkHttpClient getOkHttpAuthClient(String username, String password) + { + OkHttpClient httpClient = new OkHttpClient.Builder().build(); + OkHttpClient.Builder builder = httpClient.newBuilder(); + builder.addInterceptor(basicAuth(username, password)); + return builder.build(); + } + + public boolean authorizeHiveResource(String database, String table, String column, String accessType, String user, Set userGroups) + { + String keyDatabase = "database"; + String keyTable = "table"; + String keyColumn = "column"; + + RangerAccessResourceImpl resource = new RangerAccessResourceImpl(); + if (!StringUtils.isNullOrEmpty(database)) { + resource.setValue(keyDatabase, database); + } + + if (!StringUtils.isNullOrEmpty(table)) { + resource.setValue(keyTable, table); + } + + if (!StringUtils.isNullOrEmpty(column)) { + resource.setValue(keyColumn, column); + } + + RangerAccessRequest request = new RangerAccessRequestImpl(resource, accessType, user, userGroups); + + RangerAccessResult result = plugin.isAccessAllowed(request); + + return result != null && result.getIsAllowed(); + } + + private static Response doRequest(OkHttpClient httpClient, String anyURL) + throws IOException + { + Request request = new Request.Builder().url(anyURL).header("Accept", "application/json").build(); + Response response = httpClient.newCall(request).execute(); + if (!response.isSuccessful()) { + throw new IOException("Unexpected code " + response); + } + return response; + } +} diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java new file mode 100644 index 0000000000000..9e6db5552c44f --- /dev/null +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java @@ -0,0 +1,493 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.facebook.airlift.json.JsonCodec; +import com.facebook.airlift.log.Logger; +import com.facebook.presto.client.JsonResponse; +import com.facebook.presto.spi.SchemaTableName; +import com.facebook.presto.spi.connector.ConnectorAccessControl; +import com.facebook.presto.spi.connector.ConnectorTransactionHandle; +import com.facebook.presto.spi.security.AccessControlContext; +import com.facebook.presto.spi.security.AccessDeniedException; +import com.facebook.presto.spi.security.ConnectorIdentity; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.ranger.plugin.util.ServicePolicies; +import org.jetbrains.annotations.TestOnly; + +import javax.inject.Inject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URI; +import java.util.HashSet; +import java.util.Set; + +import static com.facebook.airlift.json.JsonCodec.jsonCodec; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_MGR_DOWNLOAD_URL; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_USER_GROUP_URL; +import static com.facebook.presto.spi.security.AccessDeniedException.denyAddColumn; +import static com.facebook.presto.spi.security.AccessDeniedException.denyCreateTable; +import static com.facebook.presto.spi.security.AccessDeniedException.denyCreateView; +import static com.facebook.presto.spi.security.AccessDeniedException.denyCreateViewWithSelect; +import static com.facebook.presto.spi.security.AccessDeniedException.denyDeleteTable; +import static com.facebook.presto.spi.security.AccessDeniedException.denyDropColumn; +import static com.facebook.presto.spi.security.AccessDeniedException.denyDropSchema; +import static com.facebook.presto.spi.security.AccessDeniedException.denyDropTable; +import static com.facebook.presto.spi.security.AccessDeniedException.denyDropView; +import static com.facebook.presto.spi.security.AccessDeniedException.denyInsertTable; +import static com.facebook.presto.spi.security.AccessDeniedException.denyRenameColumn; +import static com.facebook.presto.spi.security.AccessDeniedException.denyRenameTable; +import static com.facebook.presto.spi.security.AccessDeniedException.denySelectColumns; +import static com.google.common.net.HttpHeaders.AUTHORIZATION; +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +/** + * Connector access control which uses existing Ranger policies for authorizations + */ + +public class RangerBasedAccessControl + implements ConnectorAccessControl +{ + private static final Logger log = Logger.get(RangerBasedAccessControl.class); + + private RangerAuthorizer rangerAuthorizer; + private Users users; + + @TestOnly + public RangerBasedAccessControl() + { + } + + @Inject + public RangerBasedAccessControl(RangerBasedAccessControlConfig config) + { + requireNonNull(config.getRangerHttpEndPoint(), "Ranger service http end point is null"); + requireNonNull(config.getRangerHiveServiceName(), "Ranger hive service name is null"); + + OkHttpClient httpClient = null; + ServicePolicies servicePolicies; + try { + OkHttpClient client = getAuthHttpClient(config.getBasicAuthUser(), config.getBasicAuthPassword()); + HttpUrl hiveServicePolicyUrl = requireNonNull(HttpUrl.get(URI.create(config.getRangerHttpEndPoint()))) + .newBuilder() + .encodedPath(RANGER_REST_POLICY_MGR_DOWNLOAD_URL + "/" + config.getRangerHiveServiceName()).build(); + + HttpUrl getUsersUrl = HttpUrl.get(URI.create(config.getRangerHttpEndPoint())) + .newBuilder() + .encodedPath(RANGER_REST_USER_GROUP_URL) + .build(); + + servicePolicies = getHiveServicePolicies(client, hiveServicePolicyUrl); + users = getUsers(client, getUsersUrl); + rangerAuthorizer = new RangerAuthorizer(servicePolicies); + } + catch (Exception e) { + log.error("Exception while querying ranger service " + e); + throw new AccessDeniedException("Exception while querying ranger service "); + } + } + + private ServicePolicies getHiveServicePolicies(OkHttpClient client, HttpUrl httpUrl) + throws IOException + { + Response response = doRequest(client, httpUrl); + if (!response.isSuccessful()) { + throw new RuntimeException(format("Request to %s failed: [Error: %s]", httpUrl, response)); + } + + return jsonParse(response, ServicePolicies.class); + } + + private Users getUsers(OkHttpClient client, HttpUrl endPtUri) + { + Request request = new Request.Builder().url(endPtUri).header("Accept", "application/json").build(); + + JsonCodec usersJsonCodec = jsonCodec(Users.class); + JsonResponse users = JsonResponse.execute(usersJsonCodec, client, request); + if (!users.hasValue()) { + throw new RuntimeException(format("Request to %s failed: %s [Error: %s]", endPtUri, users, users.getResponseBody())); + } + + return users.getValue(); + } + + @TestOnly + public void setRangerAuthorizer(RangerAuthorizer rangerAuthorizer) + { + this.rangerAuthorizer = rangerAuthorizer; + } + + @TestOnly + public void setUsers(Users users) + { + this.users = users; + } + + private static T jsonParse(Response response, Class clazz) + throws IOException + { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.body().byteStream())); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper.readValue(bufferedReader, clazz); + } + + private boolean userExists(String userName) + { + return users.getvXUsers().stream() + .anyMatch(user -> userName.equalsIgnoreCase(user.getName())); + } + + private Set getGroupsForUser(String username) + { + if (userExists(username)) { + return new HashSet<>(users.getvXUsers().stream() + .filter(user -> username.equalsIgnoreCase(user.getName())) + .findFirst() + .get() + .getGroupNameList()); + } + return null; + } + + enum HiveAccessType + { + NONE, CREATE, ALTER, DROP, INDEX, LOCK, SELECT, UPDATE, USE, ALL, ADMIN + } + + private boolean checkAccess(ConnectorIdentity identity, SchemaTableName tableName, String column, HiveAccessType accessType) + { + return rangerAuthorizer.authorizeHiveResource(tableName.getSchemaName(), tableName.getTableName(), column, + accessType.toString(), identity.getUser(), getGroupsForUser(identity.getUser())); + } + + /** + * Check if identity is allowed to create the specified schema in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + public void checkCanCreateSchema(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, String schemaName) + { + } + + /** + * Check if identity is allowed to drop the specified schema in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + public void checkCanDropSchema(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, String schemaName) + { + SchemaTableName schemaTableName = new SchemaTableName(schemaName, schemaName); + if (!checkAccess(identity, schemaTableName, null, HiveAccessType.DROP)) { + denyDropSchema(schemaName, format("Access denied - User [ %s ] does not have [DROP] " + + "privilege on [ %s ] ", identity.getUser(), schemaName)); + } + } + + /** + * Check if identity is allowed to execute SHOW SCHEMAS in a catalog. + *

+ * NOTE: This method is only present to give users an error message when listing is not allowed. + * The {@link #filterSchemas} method must handle filter all results for unauthorized users, + * since there are multiple way to list schemas. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanShowSchemas(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context) + { + } + + /** + * Filter the list of schemas to those visible to the identity. + */ + @Override + public Set filterSchemas(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, Set schemaNames) + { + Set allowedSchemas = new HashSet<>(); + Set groups = getGroupsForUser(identity.getUser()); + + for (String schema : schemaNames) { + if (rangerAuthorizer.authorizeHiveResource(schema, null, null, HiveAccessType.SELECT.toString(), identity.getUser(), groups)) { + allowedSchemas.add(schema); + } + } + return allowedSchemas; + } + + /** + * Check if identity is allowed to create the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanCreateTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.CREATE)) { + denyCreateTable(tableName.getTableName(), format("Access denied - User [ %s ] does not have [CREATE] " + + "privilege on [ %s ] ", identity.getUser(), tableName.getSchemaName())); + } + } + + /** + * Filter the list of tables and views to those visible to the identity. + */ + @Override + public Set filterTables(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, Set tableNames) + { + Set allowedTables = new HashSet<>(); + Set groups = getGroupsForUser(identity.getUser()); + + for (SchemaTableName table : tableNames) { + if (rangerAuthorizer.authorizeHiveResource(table.getSchemaName(), table.getTableName(), null, HiveAccessType.SELECT.toString(), identity.getUser(), groups)) { + allowedTables.add(table); + } + } + return allowedTables; + } + + /** + * Check if identity is allowed to add columns to the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanAddColumn(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.ALTER)) { + denyAddColumn(tableName.getTableName(), format("Access denied - User [ %s ] does not have [ALTER] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to drop columns from the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanDropColumn(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.ALTER)) { + denyDropColumn(tableName.getTableName(), format("Access denied - User [ %s ] does not have [ALTER] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to rename a column in the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanRenameColumn(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.ALTER)) { + denyRenameColumn(tableName.getTableName(), format("Access denied - User [ %s ] does not have [ALTER] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to select from the specified columns in a relation. The column set can be empty. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanSelectFromColumns(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName, Set columnNames) + { + Set deniedColumns = new HashSet<>(); + for (String column : columnNames) { + if (!checkAccess(identity, tableName, column, HiveAccessType.SELECT)) { + deniedColumns.add(column); + } + } + if (deniedColumns.size() > 0) { + denySelectColumns(tableName.getTableName(), columnNames, format("Access denied - User [ %s ] does not have [SELECT] " + + "privilege on all mentioned columns of [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to drop the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanDropTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.DROP)) { + denyDropTable(tableName.getTableName(), format("Access denied - User [ %s ] does not have [DROP] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to rename the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanRenameTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName, SchemaTableName newTableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.ALTER)) { + denyRenameTable(tableName.getTableName(), format("Access denied - User [ %s ] does not have [ALTER] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to show metadata of tables by executing SHOW TABLES, SHOW GRANTS etc. in a catalog. + *

+ * NOTE: This method is only present to give users an error message when listing is not allowed. + * The {@link #filterTables} method must filter all results for unauthorized users, + * since there are multiple ways to list tables. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanShowTablesMetadata(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, String schemaName) + { + } + + /** + * Check if identity is allowed to insert into the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanInsertIntoTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.UPDATE)) { + denyInsertTable(tableName.getTableName(), format("Access denied - User [ %s ] does not have [UPDATE] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to delete from the specified table in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanDeleteFromTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.UPDATE)) { + denyDeleteTable(tableName.getTableName(), format("Access denied - User [ %s ] does not have [UPDATE] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + } + + /** + * Check if identity is allowed to create the specified view in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanCreateView(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName viewName) + { + if (!checkAccess(identity, null, null, HiveAccessType.CREATE)) { + denyCreateView(viewName.getTableName(), format("Access denied - User [ %s ] does not have [CREATE] " + + "privilege on [ %s/%s ] ", identity.getUser(), viewName.getSchemaName(), viewName.getTableName())); + } + } + + /** + * Check if identity is allowed to drop the specified view in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanDropView(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName viewName) + { + if (!checkAccess(identity, viewName, null, HiveAccessType.DROP)) { + denyDropView(viewName.getTableName(), format("Access denied - User [ %s ] does not have [DROP] " + + "privilege on [ %s/%s ] ", identity.getUser(), viewName.getSchemaName(), viewName.getTableName())); + } + } + + /** + * Check if identity is allowed to create a view that selects from the specified columns in a relation. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanCreateViewWithSelectFromColumns(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, SchemaTableName tableName, Set columnNames) + { + if (!checkAccess(identity, tableName, null, HiveAccessType.CREATE)) { + denyCreateView(tableName.getTableName(), format("Access denied - User [ %s ] does not have [CREATE] " + + "privilege on [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + } + + Set deniedColumns = new HashSet<>(); + for (String column : columnNames) { + if (!checkAccess(identity, tableName, column, HiveAccessType.SELECT)) { + deniedColumns.add(column); + } + } + if (deniedColumns.size() > 0) { + denyCreateViewWithSelect(tableName.getTableName(), identity); + } + } + + /** + * Check if identity is allowed to set the specified property in this catalog. + * + * @throws AccessDeniedException if not allowed + */ + @Override + public void checkCanSetCatalogSessionProperty(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, String propertyName) + { + } + + private static Response doRequest(OkHttpClient httpClient, HttpUrl anyURL) + throws IOException + { + Request request = new Request.Builder().url(anyURL).header("Accept", "application/json").build(); + Response response = httpClient.newCall(request).execute(); + if (!response.isSuccessful()) { + throw new IOException("Unexpected code " + response); + } + return response; + } + + public static Interceptor basicAuth(String user, String password) + { + requireNonNull(user, "user is null"); + requireNonNull(password, "password is null"); + + String credential = Credentials.basic(user, password); + return chain -> chain.proceed(chain.request().newBuilder() + .header(AUTHORIZATION, credential) + .build()); + } + + private static OkHttpClient getAuthHttpClient(String username, String password) + { + OkHttpClient httpClient = new OkHttpClient.Builder().build(); + OkHttpClient.Builder builder = httpClient.newBuilder(); + builder.addInterceptor(basicAuth(username, password)); + return builder.build(); + } +} diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java new file mode 100644 index 0000000000000..153b508c86e5b --- /dev/null +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java @@ -0,0 +1,105 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.facebook.airlift.configuration.Config; +import io.airlift.units.Duration; +import io.airlift.units.MinDuration; + +import javax.validation.constraints.NotNull; + +import java.util.concurrent.TimeUnit; + +public class RangerBasedAccessControlConfig +{ + public static final String RANGER_POLICY_REFRESH_PERIOD = "hive.ranger.refresh-policy-period"; + public static final String RANGER_HTTP_END_POINT = "hive.ranger.rest-endpoint"; + public static final String RANGER_REST_POLICY_HIVE_SERVICE_NAME = "hive.ranger.policy.hive-servicename"; + public static final String RANGER_REST_USER_GROUPS_AUTH_USERNAME = "hive.ranger.service.basic-auth-username"; + public static final String RANGER_REST_USER_GROUPS_AUTH_PASSWORD = "hive.ranger.service.basic-auth-password"; + + public static final String RANGER_REST_POLICY_MGR_DOWNLOAD_URL = "/service/plugins/policies/download"; + public static final String RANGER_REST_USER_GROUP_URL = "/service/xusers/users"; + + private String rangerHttpEndPoint; + private String rangerHiveServiceName; + private Duration refreshPeriod = new Duration(60, TimeUnit.SECONDS); + private String basicAuthUser; + private String basicAuthPassword; + + @MinDuration("60s") + public Duration getRefreshPeriod() + { + return refreshPeriod; + } + + @Config(RANGER_POLICY_REFRESH_PERIOD) + public RangerBasedAccessControlConfig setRefreshPeriod(Duration refreshPeriod) + { + this.refreshPeriod = refreshPeriod; + return this; + } + + @NotNull + public String getRangerHiveServiceName() + { + return rangerHiveServiceName; + } + + @Config(RANGER_REST_POLICY_HIVE_SERVICE_NAME) + public RangerBasedAccessControlConfig setRangerHiveServiceName(String rangerHiveServiceName) + { + this.rangerHiveServiceName = rangerHiveServiceName; + return this; + } + + @NotNull + public String getRangerHttpEndPoint() + { + return rangerHttpEndPoint; + } + + @Config(RANGER_HTTP_END_POINT) + public RangerBasedAccessControlConfig setRangerHttpEndPoint(String rangerHttpEndPoint) + { + this.rangerHttpEndPoint = rangerHttpEndPoint; + return this; + } + + @NotNull + public String getBasicAuthUser() + { + return basicAuthUser; + } + + @Config(RANGER_REST_USER_GROUPS_AUTH_USERNAME) + public RangerBasedAccessControlConfig setBasicAuthUser(String basicAuthUser) + { + this.basicAuthUser = basicAuthUser; + return this; + } + + @NotNull + public String getBasicAuthPassword() + { + return basicAuthPassword; + } + + @Config(RANGER_REST_USER_GROUPS_AUTH_PASSWORD) + public RangerBasedAccessControlConfig setBasicAuthPassword(String basicAuthPassword) + { + this.basicAuthPassword = basicAuthPassword; + return this; + } +} diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlModule.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlModule.java new file mode 100644 index 0000000000000..3d7fbdc8064ef --- /dev/null +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlModule.java @@ -0,0 +1,54 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.facebook.airlift.log.Logger; +import com.facebook.presto.plugin.base.security.ForwardingConnectorAccessControl; +import com.facebook.presto.spi.connector.ConnectorAccessControl; +import com.google.inject.Binder; +import com.google.inject.Inject; +import com.google.inject.Module; +import com.google.inject.Provides; + +import static com.facebook.airlift.configuration.ConfigBinder.configBinder; +import static com.google.common.base.Suppliers.memoizeWithExpiration; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +public class RangerBasedAccessControlModule + implements Module +{ + private static final Logger log = Logger.get(RangerBasedAccessControlModule.class); + + @Override + public void configure(Binder binder) + { + configBinder(binder).bindConfig(RangerBasedAccessControlConfig.class); + } + + @Inject + @Provides + public ConnectorAccessControl getConnectorAccessControl(RangerBasedAccessControlConfig config) + { + if (config.getRefreshPeriod() != null) { + return ForwardingConnectorAccessControl.of(memoizeWithExpiration( + () -> { + return new RangerBasedAccessControl(config); + }, + config.getRefreshPeriod().toMillis(), + MILLISECONDS)); + } + return new RangerBasedAccessControl(config); + } +} diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/Users.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/Users.java new file mode 100644 index 0000000000000..1a09a8d710873 --- /dev/null +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/Users.java @@ -0,0 +1,120 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.annotation.concurrent.Immutable; + +import java.util.List; + +import static com.google.common.base.MoreObjects.toStringHelper; + +@Immutable +public class Users +{ + private Long pageSize; + private Long queryTimeMS; + private Long resultSize; + private String sortBy; + private String sortType; + private Long startIndex; + private Long totalCount; + private List vXUsers; + + @JsonCreator + public Users( + @JsonProperty("pageSize") Long pageSize, + @JsonProperty("queryTimeMS") Long queryTimeMS, + @JsonProperty("resultSize") Long resultSize, + @JsonProperty("sortBy") String sortBy, + @JsonProperty("sortType") String sortType, + @JsonProperty("startIndex") Long startIndex, + @JsonProperty("totalCount") Long totalCount, + @JsonProperty("vXUsers") List vXUsers) + { + this.pageSize = pageSize; + this.queryTimeMS = queryTimeMS; + this.resultSize = resultSize; + this.sortBy = sortBy; + this.sortType = sortType; + this.startIndex = startIndex; + this.totalCount = totalCount; + this.vXUsers = vXUsers; + } + + @JsonProperty + public Long getPageSize() + { + return pageSize; + } + + @JsonProperty + public Long getQueryTimeMS() + { + return queryTimeMS; + } + + @JsonProperty + public Long getResultSize() + { + return resultSize; + } + + @JsonProperty + public String getSortBy() + { + return sortBy; + } + + @JsonProperty + public String getSortType() + { + return sortType; + } + + @JsonProperty + public Long getStartIndex() + { + return startIndex; + } + + @JsonProperty + public Long getTotalCount() + { + return totalCount; + } + + @JsonProperty + public List getvXUsers() + { + return vXUsers; + } + + @Override + public String toString() + { + return toStringHelper(this) + .add("taskId", pageSize) + .add("queryTimeMS", queryTimeMS) + .add("resultSize", resultSize) + .add("sortBy", sortBy) + .add("sortType", sortType) + .add("startIndex", startIndex) + .add("totalCount", totalCount) + .add("vXUsers", vXUsers) + .toString(); + } +} diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/VXUser.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/VXUser.java new file mode 100644 index 0000000000000..2a320473c1741 --- /dev/null +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/VXUser.java @@ -0,0 +1,180 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.annotation.concurrent.Immutable; + +import java.util.List; + +import static com.google.common.base.MoreObjects.toStringHelper; + +@Immutable +public class VXUser +{ + private final String createDate; + private final String description; + private final String firstName; + private final List groupIdList; + private final List groupNameList; + private final Long id; + private final Long isVisible; + private final String lastName; + private final String name; + private final String password; + private final Long status; + private final String updateDate; + private final List userRoleList; + private final Long userSource; + + @JsonCreator + public VXUser( + @JsonProperty("createDate") String createDate, + @JsonProperty("description") String description, + @JsonProperty("firstName") String firstName, + @JsonProperty("groupIdList") List groupIdList, + @JsonProperty("groupNameList") List groupNameList, + @JsonProperty("id") Long id, + @JsonProperty("isVisible") Long isVisible, + @JsonProperty("lastName") String lastName, + @JsonProperty("name") String name, + @JsonProperty("password") String password, + @JsonProperty("status") Long status, + @JsonProperty("updateDate") String updateDate, + @JsonProperty("userRoleList") List userRoleList, + @JsonProperty("userSource") Long userSource) + { + this.createDate = createDate; + this.description = description; + this.firstName = firstName; + this.groupIdList = groupIdList; + this.groupNameList = groupNameList; + this.id = id; + this.isVisible = isVisible; + this.lastName = lastName; + this.name = name; + this.password = password; + this.status = status; + this.updateDate = updateDate; + this.userRoleList = userRoleList; + this.userSource = userSource; + } + + @JsonProperty + public String getCreateDate() + { + return createDate; + } + + @JsonProperty + public String getDescription() + { + return description; + } + + @JsonProperty + public String getFirstName() + { + return firstName; + } + + @JsonProperty + public List getGroupIdList() + { + return groupIdList; + } + + @JsonProperty + public List getGroupNameList() + { + return groupNameList; + } + + @JsonProperty + public Long getId() + { + return id; + } + + @JsonProperty + public Long getIsVisible() + { + return isVisible; + } + + @JsonProperty + public String getLastName() + { + return lastName; + } + + @JsonProperty + public String getName() + { + return name; + } + + @JsonProperty + public String getPassword() + { + return password; + } + + @JsonProperty + public Long getStatus() + { + return status; + } + + @JsonProperty + public String getUpdateDate() + { + return updateDate; + } + + @JsonProperty + public List getUserRoleList() + { + return userRoleList; + } + + @JsonProperty + public Long getUserSource() + { + return userSource; + } + + @Override + public String toString() + { + return toStringHelper(this) + .add("createDate", createDate) + .add("description", description) + .add("firstName", firstName) + .add("groupIdList", groupIdList) + .add("groupNameList", groupNameList) + .add("id", id) + .add("isVisible", isVisible) + .add("lastName", lastName) + .add("password", password) + .add("status", status) + .add("updateDate", updateDate) + .add("userRoleList", userRoleList) + .add("userSource", userSource) + .toString(); + } +} diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java new file mode 100644 index 0000000000000..859fdf6297cd9 --- /dev/null +++ b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java @@ -0,0 +1,183 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.facebook.presto.spi.QueryId; +import com.facebook.presto.spi.SchemaTableName; +import com.facebook.presto.spi.connector.ConnectorAccessControl; +import com.facebook.presto.spi.connector.ConnectorTransactionHandle; +import com.facebook.presto.spi.security.AccessControlContext; +import com.facebook.presto.spi.security.AccessDeniedException; +import com.facebook.presto.spi.security.ConnectorIdentity; +import com.facebook.presto.spi.security.PrestoPrincipal; +import com.facebook.presto.spi.security.PrincipalType; +import com.facebook.presto.spi.security.Privilege; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableSet; +import org.apache.ranger.plugin.util.ServicePolicies; +import org.testng.Assert.ThrowingRunnable; +import org.testng.annotations.Test; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Optional; + +import static org.testng.Assert.assertThrows; + +public class TestRangerBasedAccessControl +{ + public static final ConnectorTransactionHandle TRANSACTION_HANDLE = new ConnectorTransactionHandle() {}; + public static final AccessControlContext CONTEXT = new AccessControlContext(new QueryId("query_id"), Optional.empty(), Optional.empty()); + + @Test + public void testTablePriviledgesRolesNotAllowed() + throws IOException + { + ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json"); + assertDenied(() -> accessControl.checkCanRevokeTablePrivilege(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, Privilege.SELECT, + new SchemaTableName("foodmart", "test"), new PrestoPrincipal(PrincipalType.ROLE, "role"), true)); + assertDenied(() -> accessControl.checkCanGrantTablePrivilege(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, Privilege.SELECT, + new SchemaTableName("foodmart", "test"), new PrestoPrincipal(PrincipalType.ROLE, "role"), true)); + assertDenied(() -> accessControl.checkCanCreateRole(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName", null)); + assertDenied(() -> accessControl.checkCanDropRole(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName")); + assertDenied(() -> accessControl.checkCanGrantRoles(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, ImmutableSet.of(""), + ImmutableSet.of(new PrestoPrincipal(PrincipalType.ROLE, "role")), true, Optional.empty(), "")); + assertDenied(() -> accessControl.checkCanSetRole(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName", "")); + } + + @Test + public void testDefaultAccessAllowedNotChecked() + throws IOException + { + ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json"); + accessControl.checkCanShowTablesMetadata(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName"); + accessControl.checkCanSetCatalogSessionProperty(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName"); + accessControl.checkCanCreateSchema(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName"); + accessControl.checkCanShowSchemas(TRANSACTION_HANDLE, user("anyuser"), CONTEXT); + } + + @Test + public void testDefaultTableAccessIfNotDefined() + throws IOException + { + ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json"); + accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("admin"), CONTEXT, new SchemaTableName("test", "test")); + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("test", "test"), ImmutableSet.of()); + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("bobschema", "bobtable"), ImmutableSet.of()); + accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("admin"), CONTEXT, new SchemaTableName("test", "test"), new SchemaTableName("test1", "test1")); + accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("bobschema", "bobtable")); + accessControl.checkCanDeleteFromTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("bobschema", "bobtable")); + accessControl.checkCanCreateViewWithSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("bobschema", "bobtable"), ImmutableSet.of()); + } + + @Test + public void testTableOperations() + throws IOException + { + ConnectorAccessControl accessControl = createRangerAccessControl("default-schema-level-access.json", "user_groups.json"); + // 'etladmin' group have all access {group - etladmin, user - alice} + accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); + accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"), new SchemaTableName("foodmart", "test1")); + accessControl.checkCanDropTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); + accessControl.checkCanDropSchema(TRANSACTION_HANDLE, user("alice"), CONTEXT, "foodmart"); + accessControl.checkCanAddColumn(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); + accessControl.checkCanDropColumn(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); + accessControl.checkCanRenameColumn(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); + + // 'analyst' group have all but drop access {group - analyst, user - joe} + accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test")); + assertDenied(() -> accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test"), new SchemaTableName("foodmart", "test1"))); + assertDenied(() -> accessControl.checkCanDropTable(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test"))); + assertDenied(() -> accessControl.checkCanDropSchema(TRANSACTION_HANDLE, user("joe"), CONTEXT, "foodmart")); + assertDenied(() -> accessControl.checkCanAddColumn(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test"))); + assertDenied(() -> accessControl.checkCanDropColumn(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test"))); + assertDenied(() -> accessControl.checkCanRenameColumn(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test"))); + + // Access denied to others {group - readall, user - bob} + assertDenied(() -> accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"), ImmutableSet.of("column1"))); + assertDenied(() -> accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"))); + assertDenied(() -> accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"), new SchemaTableName("foodmart", "test1"))); + assertDenied(() -> accessControl.checkCanDropTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"))); + assertDenied(() -> accessControl.checkCanAddColumn(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"))); + assertDenied(() -> accessControl.checkCanDropColumn(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"))); + assertDenied(() -> accessControl.checkCanRenameColumn(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"))); + } + + @Test + public void testSelectUpdateAccess() + throws IOException + { + ConnectorAccessControl accessControl = createRangerAccessControl("default-table-select-update.json", "user_groups.json"); + // 'etladmin' group have all access {group - etladmin, user - alice} + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"), ImmutableSet.of("column1")); + accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); + + // 'analyst' group have SELECT, UPDATE {group - analyst, user - joe} + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test"), ImmutableSet.of("column1")); + accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "test")); + + // Access denied to others {group - readall, user - bob} + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"), ImmutableSet.of("column1")); + assertDenied(() -> accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "test"))); + } + + @Test + public void testColumnLevelAccess() + throws IOException + { + ConnectorAccessControl accessControl = createRangerAccessControl("default-table-column-access.json", "user_groups.json"); + // 'analyst' group have read acces {group - analyst, user - joe} + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "salary"), ImmutableSet.of("currency_id", "overtime_paid")); + + // Access denied to others {group - readall, user - bob} + assertDenied(() -> accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "salary"), ImmutableSet.of("currency_id", "overtime_paid"))); + } + + private static ConnectorIdentity user(String name) + { + return new ConnectorIdentity(name, Optional.empty(), Optional.empty()); + } + + private ConnectorAccessControl createRangerAccessControl(String policyFile, String usersFile) + throws IOException + { + String policyFilePath = this.getClass().getClassLoader().getResource("com.facebook.presto.hive.security.ranger/" + policyFile).getPath(); + String usersFilePath = this.getClass().getClassLoader().getResource("com.facebook.presto.hive.security.ranger/" + usersFile).getPath(); + + ServicePolicies servicePolicies = jsonParse(new File(policyFilePath), ServicePolicies.class); + Users users = jsonParse(new File(usersFilePath), Users.class); + RangerBasedAccessControl rangerBasedAccessControl = new RangerBasedAccessControl(); + RangerAuthorizer rangerAuthorizer = new RangerAuthorizer(servicePolicies); + rangerBasedAccessControl.setRangerAuthorizer(rangerAuthorizer); + rangerBasedAccessControl.setUsers(users); + return rangerBasedAccessControl; + } + + private static T jsonParse(File file, Class clazz) + throws IOException + { + BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper.readValue(bufferedReader, clazz); + } + + private static void assertDenied(ThrowingRunnable runnable) + { + assertThrows(AccessDeniedException.class, runnable); + } +} diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java new file mode 100644 index 0000000000000..549a956d79512 --- /dev/null +++ b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java @@ -0,0 +1,118 @@ +/* + * Licensed 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 com.facebook.presto.hive.security.ranger; + +import com.facebook.airlift.configuration.ConfigurationFactory; +import com.facebook.airlift.configuration.testing.ConfigAssertions; +import com.google.common.collect.ImmutableMap; +import com.google.inject.ConfigurationException; +import io.airlift.units.Duration; +import org.testng.annotations.Test; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static com.facebook.airlift.configuration.testing.ConfigAssertions.assertFullMapping; +import static com.facebook.airlift.configuration.testing.ConfigAssertions.assertRecordedDefaults; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_HTTP_END_POINT; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_POLICY_REFRESH_PERIOD; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_HIVE_SERVICE_NAME; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_USER_GROUPS_AUTH_PASSWORD; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_USER_GROUPS_AUTH_USERNAME; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class TestRangerBasedAccessControlConfig +{ + @Test + public void testDefaults() + { + assertRecordedDefaults(ConfigAssertions.recordDefaults(RangerBasedAccessControlConfig.class) + .setRefreshPeriod(new Duration(60, TimeUnit.SECONDS)) + .setRangerHttpEndPoint(null) + .setRangerHiveServiceName(null) + .setBasicAuthUser(null) + .setBasicAuthPassword(null)); + } + + @Test + public void testExplicitPropertyMappings() + { + Map properties = new ImmutableMap.Builder() + .put(RANGER_POLICY_REFRESH_PERIOD, "200s") + .put(RANGER_HTTP_END_POINT, "http://test:6080") + .put(RANGER_REST_POLICY_HIVE_SERVICE_NAME, "hiveServiceName") + .put(RANGER_REST_USER_GROUPS_AUTH_USERNAME, "admin") + .put(RANGER_REST_USER_GROUPS_AUTH_PASSWORD, "admin") + .build(); + + RangerBasedAccessControlConfig expected = new RangerBasedAccessControlConfig() + .setRefreshPeriod(new Duration(200, TimeUnit.SECONDS)) + .setRangerHttpEndPoint("http://test:6080") + .setRangerHiveServiceName("hiveServiceName") + .setBasicAuthUser("admin") + .setBasicAuthPassword("admin"); + assertFullMapping(properties, expected); + } + + @Test + public void testValidation() + { + assertThatThrownBy(() -> newInstance(ImmutableMap.of( + RANGER_POLICY_REFRESH_PERIOD, "1us", + RANGER_REST_POLICY_HIVE_SERVICE_NAME, "hive", + RANGER_HTTP_END_POINT, "http://test:6080", + RANGER_REST_USER_GROUPS_AUTH_USERNAME, "admin", + RANGER_REST_USER_GROUPS_AUTH_PASSWORD, "admin"))) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Invalid configuration property hive.ranger.refresh-policy-period"); + + assertThatThrownBy(() -> newInstance(ImmutableMap.of( + RANGER_POLICY_REFRESH_PERIOD, "120s", + RANGER_REST_POLICY_HIVE_SERVICE_NAME, "hive", + RANGER_REST_USER_GROUPS_AUTH_USERNAME, "admin", + RANGER_REST_USER_GROUPS_AUTH_PASSWORD, "admin"))) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Invalid configuration property hive.ranger.rest-endpoint: may not be null"); + + assertThatThrownBy(() -> newInstance(ImmutableMap.of( + RANGER_POLICY_REFRESH_PERIOD, "120s", + RANGER_HTTP_END_POINT, "http://test:6080", + RANGER_REST_USER_GROUPS_AUTH_USERNAME, "admin", + RANGER_REST_USER_GROUPS_AUTH_PASSWORD, "admin"))) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Invalid configuration property hive.ranger.policy.hive-servicename: may not be null"); + + assertThatThrownBy(() -> newInstance(ImmutableMap.of( + RANGER_POLICY_REFRESH_PERIOD, "120s", + RANGER_HTTP_END_POINT, "http://test:6080", + RANGER_REST_POLICY_HIVE_SERVICE_NAME, "hive", + RANGER_REST_USER_GROUPS_AUTH_PASSWORD, "admin"))) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Invalid configuration property hive.ranger.service.basic-auth-username: may not be null"); + + assertThatThrownBy(() -> newInstance(ImmutableMap.of( + RANGER_POLICY_REFRESH_PERIOD, "120s", + RANGER_HTTP_END_POINT, "http://test:6080", + RANGER_REST_POLICY_HIVE_SERVICE_NAME, "hive", + RANGER_REST_USER_GROUPS_AUTH_USERNAME, "admin"))) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Invalid configuration property hive.ranger.service.basic-auth-password: may not be null"); + } + + private static RangerBasedAccessControlConfig newInstance(Map properties) + { + ConfigurationFactory configurationFactory = new ConfigurationFactory(properties); + return configurationFactory.build(RangerBasedAccessControlConfig.class); + } +} diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-allow-all.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-allow-all.json new file mode 100644 index 0000000000000..53e876655d20e --- /dev/null +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-allow-all.json @@ -0,0 +1,564 @@ +{ + "auditMode": "audit-default", + "policies": [ + { + "allowExceptions": [], + "dataMaskPolicyItems": [], + "denyExceptions": [], + "denyPolicyItems": [], + "description": "This policy gives global permission for all users. Disable this to test Apache Ranger", + "guid": "291eab9f-3b52-4b0f-bb27-6a986aec2c80", + "id": 1, + "isAuditEnabled": true, + "isEnabled": true, + "name": "Hive Global Tables Allow", + "policyItems": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + } + ], + "conditions": [], + "delegateAdmin": true, + "groups": [ + "public" + ], + "users": [] + } + ], + "policyType": 0, + "resources": { + "column": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*", + "ToMakeUnique" + ] + }, + "database": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + }, + "table": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + } + }, + "rowFilterPolicyItems": [], + "service": "Sandbox_hive", + "version": 1 + } + ], + "policyUpdateTime": 1607322384000, + "policyVersion": 31, + "serviceDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + }, + { + "impliedGrants": [], + "itemId": 2, + "label": "update", + "name": "update" + }, + { + "impliedGrants": [], + "itemId": 3, + "label": "Create", + "name": "create" + }, + { + "impliedGrants": [], + "itemId": 4, + "label": "Drop", + "name": "drop" + }, + { + "impliedGrants": [], + "itemId": 5, + "label": "Alter", + "name": "alter" + }, + { + "impliedGrants": [], + "itemId": 6, + "label": "Index", + "name": "index" + }, + { + "impliedGrants": [], + "itemId": 7, + "label": "Lock", + "name": "lock" + }, + { + "impliedGrants": [ + "select", + "update", + "create", + "drop", + "alter", + "index", + "lock", + "read", + "write", + "repladmin", + "serviceadmin" + ], + "itemId": 8, + "label": "All", + "name": "all" + }, + { + "impliedGrants": [], + "itemId": 9, + "label": "Read", + "name": "read" + }, + { + "impliedGrants": [], + "itemId": 10, + "label": "Write", + "name": "write" + }, + { + "impliedGrants": [], + "itemId": 11, + "label": "ReplAdmin", + "name": "repladmin" + }, + { + "impliedGrants": [], + "itemId": 12, + "label": "Service Admin", + "name": "serviceadmin" + } + ], + "configs": [ + { + "itemId": 1, + "label": "Username", + "mandatory": true, + "name": "username", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 2, + "label": "Password", + "mandatory": true, + "name": "password", + "type": "password", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "org.apache.hive.jdbc.HiveDriver", + "itemId": 3, + "mandatory": true, + "name": "jdbc.driverClassName", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "", + "itemId": 4, + "mandatory": true, + "name": "jdbc.url", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 5, + "label": "Common Name for Certificate", + "mandatory": false, + "name": "commonNameForCertificate", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "contextEnrichers": [], + "createTime": 1529337235000, + "dataMaskDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "maskTypes": [ + { + "dataMaskOptions": {}, + "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'", + "itemId": 1, + "label": "Redact", + "name": "MASK", + "transformer": "mask({col})" + }, + { + "dataMaskOptions": {}, + "description": "Show last 4 characters; replace rest with 'x'", + "itemId": 2, + "label": "Partial mask: show last 4", + "name": "MASK_SHOW_LAST_4", + "transformer": "mask_show_last_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Show first 4 characters; replace rest with 'x'", + "itemId": 3, + "label": "Partial mask: show first 4", + "name": "MASK_SHOW_FIRST_4", + "transformer": "mask_show_first_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Hash the value", + "itemId": 4, + "label": "Hash", + "name": "MASK_HASH", + "transformer": "mask_hash({col})" + }, + { + "dataMaskOptions": {}, + "description": "Replace with NULL", + "itemId": 5, + "label": "Nullify", + "name": "MASK_NULL" + }, + { + "dataMaskOptions": {}, + "description": "No masking", + "itemId": 6, + "label": "Unmasked (retain original value)", + "name": "MASK_NONE" + }, + { + "dataMaskOptions": {}, + "description": "Date: show only year", + "itemId": 12, + "label": "Date: show only year", + "name": "MASK_DATE_SHOW_YEAR", + "transformer": "mask({col}, 'x', 'x', 'x', -1, '1', 1, 0, -1)" + }, + { + "dataMaskOptions": {}, + "description": "Custom", + "itemId": 13, + "label": "Custom", + "name": "CUSTOM" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": false, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "description": "Hive Server2", + "enums": [], + "guid": "3e1afb5a-184a-4e82-9d9c-87a5cacc243c", + "id": 3, + "implClass": "org.apache.ranger.services.hive.RangerServiceHive", + "isEnabled": true, + "label": "Hive Server2", + "name": "hive", + "options": { + "enableDenyAndExceptionsInPolicies": "true" + }, + "policyConditions": [], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": true, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "URL", + "excludesSupported": false, + "itemId": 5, + "label": "URL", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "url", + "recursiveSupported": true, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Service", + "excludesSupported": false, + "itemId": 6, + "label": "Hive Service", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "hiveservice", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": true, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive UDF", + "excludesSupported": true, + "itemId": 3, + "label": "Hive UDF", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "udf", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": true, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "rowFilterDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "updateTime": 1529337417000, + "version": 9 + }, + "serviceId": 6, + "serviceName": "Sandbox_hive" +} diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-schema-level-access.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-schema-level-access.json new file mode 100644 index 0000000000000..afe012dcb8f75 --- /dev/null +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-schema-level-access.json @@ -0,0 +1,748 @@ +{ + "auditMode": "audit-default", + "policies": [ + { + "allowExceptions": [], + "dataMaskPolicyItems": [], + "denyExceptions": [], + "denyPolicyItems": [], + "description": "This policy gives global permission for all users. Disable this to test Apache Ranger", + "guid": "291eab9f-3b52-4b0f-bb27-6a986aec2c80", + "id": 1, + "isAuditEnabled": true, + "isEnabled": true, + "name": "Hive Global Tables Allow", + "policyItems": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + } + ], + "conditions": [], + "delegateAdmin": true, + "groups": [ + "public" + ], + "users": [] + } + ], + "policyType": 0, + "resources": { + "column": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*", + "ToMakeUnique" + ] + }, + "database": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + }, + "table": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + } + }, + "rowFilterPolicyItems": [], + "service": "Sandbox_hive", + "version": 1 + }, + { + "allowExceptions": [], + "dataMaskPolicyItems": [], + "denyExceptions": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "read" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "analyst" + ], + "users": [] + }, + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + }, + { + "isAllowed": true, + "type": "read" + }, + { + "isAllowed": true, + "type": "write" + }, + { + "isAllowed": true, + "type": "repladmin" + }, + { + "isAllowed": true, + "type": "serviceadmin" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "etladmin" + ], + "users": [] + } + ], + "denyPolicyItems": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + }, + { + "isAllowed": true, + "type": "read" + }, + { + "isAllowed": true, + "type": "write" + }, + { + "isAllowed": true, + "type": "repladmin" + }, + { + "isAllowed": true, + "type": "serviceadmin" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "public" + ], + "users": [] + } + ], + "description": "", + "guid": "1949d600-3b88-4393-8fc4-b3b696fef769", + "id": 26, + "isAuditEnabled": true, + "isEnabled": true, + "name": "schema access", + "policyItems": [], + "policyType": 0, + "resources": { + "column": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + }, + "database": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "foodmart" + ] + }, + "table": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + } + }, + "rowFilterPolicyItems": [], + "service": "Sandbox_hive", + "version": 1 + } + ], + "policyUpdateTime": 1607322384000, + "policyVersion": 31, + "serviceDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + }, + { + "impliedGrants": [], + "itemId": 2, + "label": "update", + "name": "update" + }, + { + "impliedGrants": [], + "itemId": 3, + "label": "Create", + "name": "create" + }, + { + "impliedGrants": [], + "itemId": 4, + "label": "Drop", + "name": "drop" + }, + { + "impliedGrants": [], + "itemId": 5, + "label": "Alter", + "name": "alter" + }, + { + "impliedGrants": [], + "itemId": 6, + "label": "Index", + "name": "index" + }, + { + "impliedGrants": [], + "itemId": 7, + "label": "Lock", + "name": "lock" + }, + { + "impliedGrants": [ + "select", + "update", + "create", + "drop", + "alter", + "index", + "lock", + "read", + "write", + "repladmin", + "serviceadmin" + ], + "itemId": 8, + "label": "All", + "name": "all" + }, + { + "impliedGrants": [], + "itemId": 9, + "label": "Read", + "name": "read" + }, + { + "impliedGrants": [], + "itemId": 10, + "label": "Write", + "name": "write" + }, + { + "impliedGrants": [], + "itemId": 11, + "label": "ReplAdmin", + "name": "repladmin" + }, + { + "impliedGrants": [], + "itemId": 12, + "label": "Service Admin", + "name": "serviceadmin" + } + ], + "configs": [ + { + "itemId": 1, + "label": "Username", + "mandatory": true, + "name": "username", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 2, + "label": "Password", + "mandatory": true, + "name": "password", + "type": "password", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "org.apache.hive.jdbc.HiveDriver", + "itemId": 3, + "mandatory": true, + "name": "jdbc.driverClassName", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "", + "itemId": 4, + "mandatory": true, + "name": "jdbc.url", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 5, + "label": "Common Name for Certificate", + "mandatory": false, + "name": "commonNameForCertificate", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "contextEnrichers": [], + "createTime": 1529337235000, + "dataMaskDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "maskTypes": [ + { + "dataMaskOptions": {}, + "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'", + "itemId": 1, + "label": "Redact", + "name": "MASK", + "transformer": "mask({col})" + }, + { + "dataMaskOptions": {}, + "description": "Show last 4 characters; replace rest with 'x'", + "itemId": 2, + "label": "Partial mask: show last 4", + "name": "MASK_SHOW_LAST_4", + "transformer": "mask_show_last_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Show first 4 characters; replace rest with 'x'", + "itemId": 3, + "label": "Partial mask: show first 4", + "name": "MASK_SHOW_FIRST_4", + "transformer": "mask_show_first_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Hash the value", + "itemId": 4, + "label": "Hash", + "name": "MASK_HASH", + "transformer": "mask_hash({col})" + }, + { + "dataMaskOptions": {}, + "description": "Replace with NULL", + "itemId": 5, + "label": "Nullify", + "name": "MASK_NULL" + }, + { + "dataMaskOptions": {}, + "description": "No masking", + "itemId": 6, + "label": "Unmasked (retain original value)", + "name": "MASK_NONE" + }, + { + "dataMaskOptions": {}, + "description": "Date: show only year", + "itemId": 12, + "label": "Date: show only year", + "name": "MASK_DATE_SHOW_YEAR", + "transformer": "mask({col}, 'x', 'x', 'x', -1, '1', 1, 0, -1)" + }, + { + "dataMaskOptions": {}, + "description": "Custom", + "itemId": 13, + "label": "Custom", + "name": "CUSTOM" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": false, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "description": "Hive Server2", + "enums": [], + "guid": "3e1afb5a-184a-4e82-9d9c-87a5cacc243c", + "id": 3, + "implClass": "org.apache.ranger.services.hive.RangerServiceHive", + "isEnabled": true, + "label": "Hive Server2", + "name": "hive", + "options": { + "enableDenyAndExceptionsInPolicies": "true" + }, + "policyConditions": [], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": true, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "URL", + "excludesSupported": false, + "itemId": 5, + "label": "URL", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "url", + "recursiveSupported": true, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Service", + "excludesSupported": false, + "itemId": 6, + "label": "Hive Service", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "hiveservice", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": true, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive UDF", + "excludesSupported": true, + "itemId": 3, + "label": "Hive UDF", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "udf", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": true, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "rowFilterDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "updateTime": 1529337417000, + "version": 9 + }, + "serviceId": 6, + "serviceName": "Sandbox_hive" +} diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-column-access.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-column-access.json new file mode 100644 index 0000000000000..ebae418264640 --- /dev/null +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-column-access.json @@ -0,0 +1,723 @@ +{ + "auditMode": "audit-default", + "policies": [ + { + "allowExceptions": [], + "dataMaskPolicyItems": [], + "denyExceptions": [], + "denyPolicyItems": [], + "description": "This policy gives global permission for all users. Disable this to test Apache Ranger", + "guid": "291eab9f-3b52-4b0f-bb27-6a986aec2c80", + "id": 1, + "isAuditEnabled": true, + "isEnabled": true, + "name": "Hive Global Tables Allow", + "policyItems": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + } + ], + "conditions": [], + "delegateAdmin": true, + "groups": [ + "public" + ], + "users": [] + } + ], + "policyType": 0, + "resources": { + "column": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*", + "ToMakeUnique" + ] + }, + "database": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + }, + "table": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + } + }, + "rowFilterPolicyItems": [], + "service": "Sandbox_hive", + "version": 1 + }, + { + "allowExceptions": [], + "dataMaskPolicyItems": [], + "denyExceptions": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + }, + { + "isAllowed": true, + "type": "read" + }, + { + "isAllowed": true, + "type": "write" + }, + { + "isAllowed": true, + "type": "repladmin" + }, + { + "isAllowed": true, + "type": "serviceadmin" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "analyst" + ], + "users": [] + } + ], + "denyPolicyItems": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + }, + { + "isAllowed": true, + "type": "read" + }, + { + "isAllowed": true, + "type": "write" + }, + { + "isAllowed": true, + "type": "repladmin" + }, + { + "isAllowed": true, + "type": "serviceadmin" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "public" + ], + "users": [] + } + ], + "description": "", + "guid": "fe76af46-3cb6-46ef-bd96-c6167ee436ca", + "id": 27, + "isAuditEnabled": true, + "isEnabled": true, + "name": "column access", + "policyItems": [], + "policyType": 0, + "resources": { + "column": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "salary_paid", + "overtime_paid" + ] + }, + "database": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "foodmart" + ] + }, + "table": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "salary" + ] + } + }, + "rowFilterPolicyItems": [], + "service": "Sandbox_hive", + "version": 1 + } + ], + "policyUpdateTime": 1607322384000, + "policyVersion": 31, + "serviceDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + }, + { + "impliedGrants": [], + "itemId": 2, + "label": "update", + "name": "update" + }, + { + "impliedGrants": [], + "itemId": 3, + "label": "Create", + "name": "create" + }, + { + "impliedGrants": [], + "itemId": 4, + "label": "Drop", + "name": "drop" + }, + { + "impliedGrants": [], + "itemId": 5, + "label": "Alter", + "name": "alter" + }, + { + "impliedGrants": [], + "itemId": 6, + "label": "Index", + "name": "index" + }, + { + "impliedGrants": [], + "itemId": 7, + "label": "Lock", + "name": "lock" + }, + { + "impliedGrants": [ + "select", + "update", + "create", + "drop", + "alter", + "index", + "lock", + "read", + "write", + "repladmin", + "serviceadmin" + ], + "itemId": 8, + "label": "All", + "name": "all" + }, + { + "impliedGrants": [], + "itemId": 9, + "label": "Read", + "name": "read" + }, + { + "impliedGrants": [], + "itemId": 10, + "label": "Write", + "name": "write" + }, + { + "impliedGrants": [], + "itemId": 11, + "label": "ReplAdmin", + "name": "repladmin" + }, + { + "impliedGrants": [], + "itemId": 12, + "label": "Service Admin", + "name": "serviceadmin" + } + ], + "configs": [ + { + "itemId": 1, + "label": "Username", + "mandatory": true, + "name": "username", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 2, + "label": "Password", + "mandatory": true, + "name": "password", + "type": "password", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "org.apache.hive.jdbc.HiveDriver", + "itemId": 3, + "mandatory": true, + "name": "jdbc.driverClassName", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "", + "itemId": 4, + "mandatory": true, + "name": "jdbc.url", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 5, + "label": "Common Name for Certificate", + "mandatory": false, + "name": "commonNameForCertificate", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "contextEnrichers": [], + "createTime": 1529337235000, + "dataMaskDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "maskTypes": [ + { + "dataMaskOptions": {}, + "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'", + "itemId": 1, + "label": "Redact", + "name": "MASK", + "transformer": "mask({col})" + }, + { + "dataMaskOptions": {}, + "description": "Show last 4 characters; replace rest with 'x'", + "itemId": 2, + "label": "Partial mask: show last 4", + "name": "MASK_SHOW_LAST_4", + "transformer": "mask_show_last_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Show first 4 characters; replace rest with 'x'", + "itemId": 3, + "label": "Partial mask: show first 4", + "name": "MASK_SHOW_FIRST_4", + "transformer": "mask_show_first_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Hash the value", + "itemId": 4, + "label": "Hash", + "name": "MASK_HASH", + "transformer": "mask_hash({col})" + }, + { + "dataMaskOptions": {}, + "description": "Replace with NULL", + "itemId": 5, + "label": "Nullify", + "name": "MASK_NULL" + }, + { + "dataMaskOptions": {}, + "description": "No masking", + "itemId": 6, + "label": "Unmasked (retain original value)", + "name": "MASK_NONE" + }, + { + "dataMaskOptions": {}, + "description": "Date: show only year", + "itemId": 12, + "label": "Date: show only year", + "name": "MASK_DATE_SHOW_YEAR", + "transformer": "mask({col}, 'x', 'x', 'x', -1, '1', 1, 0, -1)" + }, + { + "dataMaskOptions": {}, + "description": "Custom", + "itemId": 13, + "label": "Custom", + "name": "CUSTOM" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": false, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "description": "Hive Server2", + "enums": [], + "guid": "3e1afb5a-184a-4e82-9d9c-87a5cacc243c", + "id": 3, + "implClass": "org.apache.ranger.services.hive.RangerServiceHive", + "isEnabled": true, + "label": "Hive Server2", + "name": "hive", + "options": { + "enableDenyAndExceptionsInPolicies": "true" + }, + "policyConditions": [], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": true, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "URL", + "excludesSupported": false, + "itemId": 5, + "label": "URL", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "url", + "recursiveSupported": true, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Service", + "excludesSupported": false, + "itemId": 6, + "label": "Hive Service", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "hiveservice", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": true, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive UDF", + "excludesSupported": true, + "itemId": 3, + "label": "Hive UDF", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "udf", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": true, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "rowFilterDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "updateTime": 1529337417000, + "version": 9 + }, + "serviceId": 6, + "serviceName": "Sandbox_hive" +} diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-select-update.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-select-update.json new file mode 100644 index 0000000000000..d23112adf4744 --- /dev/null +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/default-table-select-update.json @@ -0,0 +1,762 @@ +{ + "auditMode": "audit-default", + "policies": [ + { + "allowExceptions": [], + "dataMaskPolicyItems": [], + "denyExceptions": [], + "denyPolicyItems": [], + "description": "This policy gives global permission for all users. Disable this to test Apache Ranger", + "guid": "291eab9f-3b52-4b0f-bb27-6a986aec2c80", + "id": 1, + "isAuditEnabled": true, + "isEnabled": true, + "name": "Hive Global Tables Allow", + "policyItems": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + } + ], + "conditions": [], + "delegateAdmin": true, + "groups": [ + "public" + ], + "users": [] + } + ], + "policyType": 0, + "resources": { + "column": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*", + "ToMakeUnique" + ] + }, + "database": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + }, + "table": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + } + }, + "rowFilterPolicyItems": [], + "service": "Sandbox_hive", + "version": 1 + }, + { + "allowExceptions": [], + "dataMaskPolicyItems": [], + "denyExceptions": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "read" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "analyst" + ], + "users": [] + }, + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + }, + { + "isAllowed": true, + "type": "read" + }, + { + "isAllowed": true, + "type": "write" + }, + { + "isAllowed": true, + "type": "repladmin" + }, + { + "isAllowed": true, + "type": "serviceadmin" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "etladmin" + ], + "users": [] + }, + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "read" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "readall" + ], + "users": [] + } + ], + "denyPolicyItems": [ + { + "accesses": [ + { + "isAllowed": true, + "type": "select" + }, + { + "isAllowed": true, + "type": "update" + }, + { + "isAllowed": true, + "type": "create" + }, + { + "isAllowed": true, + "type": "drop" + }, + { + "isAllowed": true, + "type": "alter" + }, + { + "isAllowed": true, + "type": "index" + }, + { + "isAllowed": true, + "type": "lock" + }, + { + "isAllowed": true, + "type": "all" + }, + { + "isAllowed": true, + "type": "read" + }, + { + "isAllowed": true, + "type": "write" + }, + { + "isAllowed": true, + "type": "repladmin" + }, + { + "isAllowed": true, + "type": "serviceadmin" + } + ], + "conditions": [], + "delegateAdmin": false, + "groups": [ + "public" + ], + "users": [] + } + ], + "description": "", + "guid": "1949d600-3b88-4393-8fc4-b3b696fef769", + "id": 26, + "isAuditEnabled": true, + "isEnabled": true, + "name": "select update access", + "policyItems": [], + "policyType": 0, + "resources": { + "column": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + }, + "database": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "foodmart" + ] + }, + "table": { + "isExcludes": false, + "isRecursive": false, + "values": [ + "*" + ] + } + }, + "rowFilterPolicyItems": [], + "service": "Sandbox_hive", + "version": 7 + } + ], + "policyUpdateTime": 1607322384000, + "policyVersion": 31, + "serviceDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + }, + { + "impliedGrants": [], + "itemId": 2, + "label": "update", + "name": "update" + }, + { + "impliedGrants": [], + "itemId": 3, + "label": "Create", + "name": "create" + }, + { + "impliedGrants": [], + "itemId": 4, + "label": "Drop", + "name": "drop" + }, + { + "impliedGrants": [], + "itemId": 5, + "label": "Alter", + "name": "alter" + }, + { + "impliedGrants": [], + "itemId": 6, + "label": "Index", + "name": "index" + }, + { + "impliedGrants": [], + "itemId": 7, + "label": "Lock", + "name": "lock" + }, + { + "impliedGrants": [ + "select", + "update", + "create", + "drop", + "alter", + "index", + "lock", + "read", + "write", + "repladmin", + "serviceadmin" + ], + "itemId": 8, + "label": "All", + "name": "all" + }, + { + "impliedGrants": [], + "itemId": 9, + "label": "Read", + "name": "read" + }, + { + "impliedGrants": [], + "itemId": 10, + "label": "Write", + "name": "write" + }, + { + "impliedGrants": [], + "itemId": 11, + "label": "ReplAdmin", + "name": "repladmin" + }, + { + "impliedGrants": [], + "itemId": 12, + "label": "Service Admin", + "name": "serviceadmin" + } + ], + "configs": [ + { + "itemId": 1, + "label": "Username", + "mandatory": true, + "name": "username", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 2, + "label": "Password", + "mandatory": true, + "name": "password", + "type": "password", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "org.apache.hive.jdbc.HiveDriver", + "itemId": 3, + "mandatory": true, + "name": "jdbc.driverClassName", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "defaultValue": "", + "itemId": 4, + "mandatory": true, + "name": "jdbc.url", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "itemId": 5, + "label": "Common Name for Certificate", + "mandatory": false, + "name": "commonNameForCertificate", + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "contextEnrichers": [], + "createTime": 1529337235000, + "dataMaskDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "maskTypes": [ + { + "dataMaskOptions": {}, + "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'", + "itemId": 1, + "label": "Redact", + "name": "MASK", + "transformer": "mask({col})" + }, + { + "dataMaskOptions": {}, + "description": "Show last 4 characters; replace rest with 'x'", + "itemId": 2, + "label": "Partial mask: show last 4", + "name": "MASK_SHOW_LAST_4", + "transformer": "mask_show_last_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Show first 4 characters; replace rest with 'x'", + "itemId": 3, + "label": "Partial mask: show first 4", + "name": "MASK_SHOW_FIRST_4", + "transformer": "mask_show_first_n({col}, 4, 'x', 'x', 'x', -1, '1')" + }, + { + "dataMaskOptions": {}, + "description": "Hash the value", + "itemId": 4, + "label": "Hash", + "name": "MASK_HASH", + "transformer": "mask_hash({col})" + }, + { + "dataMaskOptions": {}, + "description": "Replace with NULL", + "itemId": 5, + "label": "Nullify", + "name": "MASK_NULL" + }, + { + "dataMaskOptions": {}, + "description": "No masking", + "itemId": 6, + "label": "Unmasked (retain original value)", + "name": "MASK_NONE" + }, + { + "dataMaskOptions": {}, + "description": "Date: show only year", + "itemId": 12, + "label": "Date: show only year", + "name": "MASK_DATE_SHOW_YEAR", + "transformer": "mask({col}, 'x', 'x', 'x', -1, '1', 1, 0, -1)" + }, + { + "dataMaskOptions": {}, + "description": "Custom", + "itemId": 13, + "label": "Custom", + "name": "CUSTOM" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": false, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "description": "Hive Server2", + "enums": [], + "guid": "3e1afb5a-184a-4e82-9d9c-87a5cacc243c", + "id": 3, + "implClass": "org.apache.ranger.services.hive.RangerServiceHive", + "isEnabled": true, + "label": "Hive Server2", + "name": "hive", + "options": { + "enableDenyAndExceptionsInPolicies": "true" + }, + "policyConditions": [], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": true, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "URL", + "excludesSupported": false, + "itemId": 5, + "label": "URL", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "url", + "recursiveSupported": true, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Service", + "excludesSupported": false, + "itemId": 6, + "label": "Hive Service", + "level": 10, + "lookupSupported": false, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "false", + "wildCard": "true" + }, + "name": "hiveservice", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": true, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive UDF", + "excludesSupported": true, + "itemId": 3, + "label": "Hive UDF", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "udf", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Column", + "excludesSupported": true, + "itemId": 4, + "label": "Hive Column", + "level": 30, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "true" + }, + "name": "column", + "parent": "table", + "recursiveSupported": false, + "type": "string", + "uiHint": "", + "validationMessage": "", + "validationRegEx": "" + } + ], + "rowFilterDef": { + "accessTypes": [ + { + "impliedGrants": [], + "itemId": 1, + "label": "select", + "name": "select" + } + ], + "resources": [ + { + "description": "Hive Database", + "excludesSupported": false, + "itemId": 1, + "label": "Hive Database", + "level": 10, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + }, + { + "description": "Hive Table", + "excludesSupported": false, + "itemId": 2, + "label": "Hive Table", + "level": 20, + "lookupSupported": true, + "mandatory": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "ignoreCase": "true", + "wildCard": "false" + }, + "name": "table", + "parent": "database", + "recursiveSupported": false, + "type": "string", + "uiHint": "{ \"singleValue\":true }", + "validationMessage": "", + "validationRegEx": "" + } + ] + }, + "updateTime": 1529337417000, + "version": 9 + }, + "serviceId": 6, + "serviceName": "Sandbox_hive" +} diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json new file mode 100644 index 0000000000000..d8e41edbebe05 --- /dev/null +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json @@ -0,0 +1,87 @@ +{ + "pageSize": 200, + "queryTimeMS": 1607597349271, + "resultSize": 2, + "sortBy": "id", + "sortType": "asc", + "startIndex": 0, + "totalCount": 2, + "vXUsers": [ + { + "createDate": "2018-06-18T15:58:00Z", + "description": "alice - add from Unix box", + "firstName": "alice", + "groupIdList": [ + 14, + 3 + ], + "groupNameList": [ + "readall", + "etladmin" + ], + "id": 1, + "isVisible": 1, + "lastName": "alice", + "name": "alice", + "owner": "Admin", + "password": "*****", + "status": 1, + "updateDate": "2020-10-13T10:03:10Z", + "updatedBy": "Admin", + "userRoleList": [ + "ROLE_USER" + ], + "userSource": 1 + }, + { + "createDate": "2018-06-18T15:58:00Z", + "description": "bob - add from Unix box", + "firstName": "bob", + "groupIdList": [ + 14, + 3 + ], + "groupNameList": [ + "readall" + ], + "id": 2, + "isVisible": 1, + "lastName": "bob", + "name": "bob", + "owner": "Admin", + "password": "*****", + "status": 1, + "updateDate": "2020-10-13T10:03:10Z", + "updatedBy": "Admin", + "userRoleList": [ + "ROLE_USER" + ], + "userSource": 1 + }, + { + "createDate": "2018-06-18T15:58:00Z", + "description": "joe - add from Unix box", + "firstName": "joe", + "groupIdList": [ + 14, + 3 + ], + "groupNameList": [ + "analyst" + ], + "id": 3, + "isVisible": 1, + "lastName": "joe", + "name": "joe", + "owner": "Admin", + "password": "*****", + "status": 1, + "updateDate": "2020-10-13T10:03:10Z", + "updatedBy": "Admin", + "userRoleList": [ + "ROLE_USER" + ], + "userSource": 1 + } + ] +} From ab93f1c8ff74fa555b575a157dae2da20bfb811d Mon Sep 17 00:00:00 2001 From: Ashish Tadose Date: Mon, 28 Jun 2021 14:57:12 +0530 Subject: [PATCH 2/5] Upgrade ranger to 2.1 --- presto-hive/pom.xml | 113 +++++++++++++++++- .../security/ranger/RangerAuthorizer.java | 18 ++- 2 files changed, 120 insertions(+), 11 deletions(-) diff --git a/presto-hive/pom.xml b/presto-hive/pom.xml index 66a7b4ef99b93..b7e475c3d8c6e 100644 --- a/presto-hive/pom.xml +++ b/presto-hive/pom.xml @@ -254,7 +254,7 @@ org.apache.ranger ranger-plugins-common - 0.7.1 + 2.1.0 log4j @@ -273,12 +273,8 @@ org.apache.kafka - jersey-bundle - com.sun.jersey - - - commons-logging commons-logging + commons-logging commons-logging @@ -300,6 +296,111 @@ org.eclipse.persistence javax.persistence + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + joda-time + joda-time + + + com.fasterxml.jackson.core + jackson-core + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpcore + + + org.apache.httpcomponents + httpcore-nio + + + org.apache.httpcomponents + httpasyncclient + + + commons-codec + commons-codec + + + org.slf4j + slf4j-api + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-cbor + + + org.apache.kafka + kafka-clients + + + org.apache.lucene + lucene-analyzers-common + + + org.apache.zookeeper + zookeeper + + + com.carrotsearch + hppc + + + net.sf.jopt-simple + jopt-simple + + + net.java.dev.jna + jna + + + org.scala-lang + scala-library + + + org.scala-lang + scala-reflect + + + com.sun.jersey + jersey-bundle + + + jna-platform + net.java.dev.jna + + + + + + com.sun.jersey + jersey-client + 1.19 + runtime + + + javax.ws.rs + javax.ws.rs-api + + + javax.ws.rs + jsr311-api + diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java index 9c33933f1a67f..31f3d95318a22 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java @@ -20,10 +20,13 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.apache.hadoop.conf.Configuration; +import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl; import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl; import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; import org.apache.ranger.plugin.service.RangerBasePlugin; import org.apache.ranger.plugin.util.ServicePolicies; @@ -33,6 +36,7 @@ import java.util.Set; import static com.google.common.net.HttpHeaders.AUTHORIZATION; +import static java.util.Locale.ENGLISH; import static java.util.Objects.requireNonNull; public class RangerAuthorizer @@ -41,7 +45,14 @@ public class RangerAuthorizer public RangerAuthorizer(ServicePolicies servicePolicies) { - plugin = new RangerBasePlugin("hive", "standalone-hive"); + + RangerPolicyEngineOptions rangerPolicyEngineOptions = new RangerPolicyEngineOptions(); + Configuration conf = new Configuration(); + conf.set("hive.policyengine.option.disable.tagpolicy.evaluation", "true"); + rangerPolicyEngineOptions.configureForPlugin(conf, "hive"); + RangerPluginConfig rangerPluginConfig = new RangerPluginConfig("hive", null, "standalone-hive", null, null, + rangerPolicyEngineOptions); + plugin = new RangerBasePlugin(rangerPluginConfig); plugin.setResultProcessor(null); plugin.setPolicies(servicePolicies); } @@ -78,7 +89,6 @@ public boolean authorizeHiveResource(String database, String table, String colum String keyDatabase = "database"; String keyTable = "table"; String keyColumn = "column"; - RangerAccessResourceImpl resource = new RangerAccessResourceImpl(); if (!StringUtils.isNullOrEmpty(database)) { resource.setValue(keyDatabase, database); @@ -92,10 +102,8 @@ public boolean authorizeHiveResource(String database, String table, String colum resource.setValue(keyColumn, column); } - RangerAccessRequest request = new RangerAccessRequestImpl(resource, accessType, user, userGroups); - + RangerAccessRequest request = new RangerAccessRequestImpl(resource, accessType.toLowerCase(ENGLISH), user, userGroups, null); RangerAccessResult result = plugin.isAccessAllowed(request); - return result != null && result.getIsAllowed(); } From 888f364bc0ac492af6224c5876b801d85feae9fe Mon Sep 17 00:00:00 2001 From: Ashish Tadose Date: Mon, 28 Jun 2021 16:20:55 +0530 Subject: [PATCH 3/5] Support to access Ranger REST resources on secured ssl server --- .../security/ranger/RangerAuthorizer.java | 12 ---- .../ranger/RangerBasedAccessControl.java | 29 +++++++--- .../RangerBasedAccessControlConfig.java | 57 +++++++++++++++++++ .../TestRangerBasedAccessControlConfig.java | 20 ++++++- 4 files changed, 95 insertions(+), 23 deletions(-) diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java index 31f3d95318a22..0baf8e3e138a7 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java @@ -14,7 +14,6 @@ package com.facebook.presto.hive.security.ranger; import com.amazonaws.util.StringUtils; -import com.fasterxml.jackson.databind.ObjectMapper; import okhttp3.Credentials; import okhttp3.Interceptor; import okhttp3.OkHttpClient; @@ -30,9 +29,7 @@ import org.apache.ranger.plugin.service.RangerBasePlugin; import org.apache.ranger.plugin.util.ServicePolicies; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.util.Set; import static com.google.common.net.HttpHeaders.AUTHORIZATION; @@ -45,7 +42,6 @@ public class RangerAuthorizer public RangerAuthorizer(ServicePolicies servicePolicies) { - RangerPolicyEngineOptions rangerPolicyEngineOptions = new RangerPolicyEngineOptions(); Configuration conf = new Configuration(); conf.set("hive.policyengine.option.disable.tagpolicy.evaluation", "true"); @@ -57,14 +53,6 @@ public RangerAuthorizer(ServicePolicies servicePolicies) plugin.setPolicies(servicePolicies); } - private static T jsonParse(Response response, Class clazz) - throws IOException - { - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.body().byteStream())); - ObjectMapper mapper = new ObjectMapper(); - return mapper.readValue(bufferedReader, clazz); - } - public static Interceptor basicAuth(String user, String password) { requireNonNull(user, "user is null"); diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java index 9e6db5552c44f..d2b94c052dbb4 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java @@ -16,6 +16,7 @@ import com.facebook.airlift.json.JsonCodec; import com.facebook.airlift.log.Logger; import com.facebook.presto.client.JsonResponse; +import com.facebook.presto.client.OkHttpUtil; import com.facebook.presto.spi.SchemaTableName; import com.facebook.presto.spi.connector.ConnectorAccessControl; import com.facebook.presto.spi.connector.ConnectorTransactionHandle; @@ -40,6 +41,7 @@ import java.io.InputStreamReader; import java.net.URI; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import static com.facebook.airlift.json.JsonCodec.jsonCodec; @@ -88,12 +90,13 @@ public RangerBasedAccessControl(RangerBasedAccessControlConfig config) OkHttpClient httpClient = null; ServicePolicies servicePolicies; try { - OkHttpClient client = getAuthHttpClient(config.getBasicAuthUser(), config.getBasicAuthPassword()); + OkHttpClient client = getAuthHttpClient(config); + HttpUrl hiveServicePolicyUrl = requireNonNull(HttpUrl.get(URI.create(config.getRangerHttpEndPoint()))) .newBuilder() .encodedPath(RANGER_REST_POLICY_MGR_DOWNLOAD_URL + "/" + config.getRangerHiveServiceName()).build(); - HttpUrl getUsersUrl = HttpUrl.get(URI.create(config.getRangerHttpEndPoint())) + HttpUrl getUsersUrl = requireNonNull(HttpUrl.get(URI.create(config.getRangerHttpEndPoint()))) .newBuilder() .encodedPath(RANGER_REST_USER_GROUP_URL) .build(); @@ -103,7 +106,7 @@ public RangerBasedAccessControl(RangerBasedAccessControlConfig config) rangerAuthorizer = new RangerAuthorizer(servicePolicies); } catch (Exception e) { - log.error("Exception while querying ranger service " + e); + log.error("Exception while querying ranger service ", e); throw new AccessDeniedException("Exception while querying ranger service "); } } @@ -147,10 +150,14 @@ public void setUsers(Users users) private static T jsonParse(Response response, Class clazz) throws IOException { - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.body().byteStream())); - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - return mapper.readValue(bufferedReader, clazz); + if (response.body() != null) { + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.body().byteStream()))) { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper.readValue(bufferedReader, clazz); + } + } + return null; } private boolean userExists(String userName) @@ -483,11 +490,15 @@ public static Interceptor basicAuth(String user, String password) .build()); } - private static OkHttpClient getAuthHttpClient(String username, String password) + private static OkHttpClient getAuthHttpClient(RangerBasedAccessControlConfig controlConfig) { OkHttpClient httpClient = new OkHttpClient.Builder().build(); OkHttpClient.Builder builder = httpClient.newBuilder(); - builder.addInterceptor(basicAuth(username, password)); + OkHttpUtil.setupSsl(builder, Optional.ofNullable(controlConfig.getRangerRestKeystorePath()), + Optional.ofNullable(controlConfig.getRangerRestKeystorePwd()), + Optional.ofNullable(controlConfig.getRangerRestTruststorePath()), + Optional.ofNullable(controlConfig.getRangerRestTruststorePwd())); + builder.addInterceptor(basicAuth(controlConfig.getBasicAuthUser(), controlConfig.getBasicAuthPassword())); return builder.build(); } } diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java index 153b508c86e5b..c4026027f0f84 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java @@ -32,11 +32,20 @@ public class RangerBasedAccessControlConfig public static final String RANGER_REST_POLICY_MGR_DOWNLOAD_URL = "/service/plugins/policies/download"; public static final String RANGER_REST_USER_GROUP_URL = "/service/xusers/users"; + public static final String RANGER_REST_POLICY_MGR_KEYSTORE_PATH = "hive.ranger.service.keystore.path"; + public static final String RANGER_REST_POLICY_MGR_KEYSTORE_PWD = "hive.ranger.service.keystore.password"; + public static final String RANGER_REST_POLICY_MGR_TRUST_STORE_PATH = "hive.ranger.service.truststore.path"; + public static final String RANGER_REST_POLICY_MGR_TRUST_STORE_PWD = "hive.ranger.service.truststore.password"; + private String rangerHttpEndPoint; private String rangerHiveServiceName; private Duration refreshPeriod = new Duration(60, TimeUnit.SECONDS); private String basicAuthUser; private String basicAuthPassword; + private String rangerRestKeystorePath; + private String rangerRestKeystorePwd; + private String rangerRestTruststorePath; + private String rangerRestTruststorePwd; @MinDuration("60s") public Duration getRefreshPeriod() @@ -102,4 +111,52 @@ public RangerBasedAccessControlConfig setBasicAuthPassword(String basicAuthPassw this.basicAuthPassword = basicAuthPassword; return this; } + + public String getRangerRestKeystorePath() + { + return rangerRestKeystorePath; + } + + @Config(RANGER_REST_POLICY_MGR_KEYSTORE_PATH) + public RangerBasedAccessControlConfig setRangerRestKeystorePath(String rangerRestKeystorePath) + { + this.rangerRestKeystorePath = rangerRestKeystorePath; + return this; + } + + public String getRangerRestKeystorePwd() + { + return rangerRestKeystorePwd; + } + + @Config(RANGER_REST_POLICY_MGR_KEYSTORE_PWD) + public RangerBasedAccessControlConfig setRangerRestKeystorePwd(String rangerRestKeystorePwd) + { + this.rangerRestKeystorePwd = rangerRestKeystorePwd; + return this; + } + + public String getRangerRestTruststorePath() + { + return rangerRestTruststorePath; + } + + @Config(RANGER_REST_POLICY_MGR_TRUST_STORE_PATH) + public RangerBasedAccessControlConfig setRangerRestTruststorePath(String rangerRestTruststorePath) + { + this.rangerRestTruststorePath = rangerRestTruststorePath; + return this; + } + + public String getRangerRestTruststorePwd() + { + return rangerRestTruststorePwd; + } + + @Config(RANGER_REST_POLICY_MGR_TRUST_STORE_PWD) + public RangerBasedAccessControlConfig setRangerRestTruststorePwd(String rangerRestTruststorePwd) + { + this.rangerRestTruststorePwd = rangerRestTruststorePwd; + return this; + } } diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java index 549a956d79512..766f64765fb09 100644 --- a/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java +++ b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControlConfig.java @@ -28,6 +28,10 @@ import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_HTTP_END_POINT; import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_POLICY_REFRESH_PERIOD; import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_HIVE_SERVICE_NAME; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_MGR_KEYSTORE_PATH; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_MGR_KEYSTORE_PWD; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_MGR_TRUST_STORE_PATH; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_MGR_TRUST_STORE_PWD; import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_USER_GROUPS_AUTH_PASSWORD; import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_USER_GROUPS_AUTH_USERNAME; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -42,7 +46,11 @@ public void testDefaults() .setRangerHttpEndPoint(null) .setRangerHiveServiceName(null) .setBasicAuthUser(null) - .setBasicAuthPassword(null)); + .setBasicAuthPassword(null) + .setRangerRestKeystorePath(null) + .setRangerRestKeystorePwd(null) + .setRangerRestTruststorePath(null) + .setRangerRestTruststorePwd(null)); } @Test @@ -54,6 +62,10 @@ public void testExplicitPropertyMappings() .put(RANGER_REST_POLICY_HIVE_SERVICE_NAME, "hiveServiceName") .put(RANGER_REST_USER_GROUPS_AUTH_USERNAME, "admin") .put(RANGER_REST_USER_GROUPS_AUTH_PASSWORD, "admin") + .put(RANGER_REST_POLICY_MGR_KEYSTORE_PATH, "key_path") + .put(RANGER_REST_POLICY_MGR_KEYSTORE_PWD, "key_pwd") + .put(RANGER_REST_POLICY_MGR_TRUST_STORE_PATH, "trust_path") + .put(RANGER_REST_POLICY_MGR_TRUST_STORE_PWD, "trust_pwd") .build(); RangerBasedAccessControlConfig expected = new RangerBasedAccessControlConfig() @@ -61,7 +73,11 @@ public void testExplicitPropertyMappings() .setRangerHttpEndPoint("http://test:6080") .setRangerHiveServiceName("hiveServiceName") .setBasicAuthUser("admin") - .setBasicAuthPassword("admin"); + .setBasicAuthPassword("admin") + .setRangerRestKeystorePath("key_path") + .setRangerRestKeystorePwd("key_pwd") + .setRangerRestTruststorePath("trust_path") + .setRangerRestTruststorePwd("trust_pwd"); assertFullMapping(properties, expected); } From d30bbb3def19afc5397b2e8a5a3d479302cbc5ed Mon Sep 17 00:00:00 2001 From: Ashish Tadose Date: Mon, 28 Jun 2021 16:52:04 +0530 Subject: [PATCH 4/5] Support to provide authorization based upon Roles defined in Ranger --- .../security/ranger/RangerAuthorizer.java | 18 +- .../ranger/RangerBasedAccessControl.java | 63 +- .../RangerBasedAccessControlConfig.java | 1 + .../ranger/TestRangerBasedAccessControl.java | 58 +- .../ranger-role-based-access.json | 1566 +++++++++++++++++ .../user_groups.json | 72 + .../user_roles.json | 14 + 7 files changed, 1773 insertions(+), 19 deletions(-) create mode 100644 presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/ranger-role-based-access.json create mode 100644 presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_roles.json diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java index 0baf8e3e138a7..333d932a17e17 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerAuthorizer.java @@ -14,6 +14,7 @@ package com.facebook.presto.hive.security.ranger; import com.amazonaws.util.StringUtils; +import com.fasterxml.jackson.databind.ObjectMapper; import okhttp3.Credentials; import okhttp3.Interceptor; import okhttp3.OkHttpClient; @@ -29,7 +30,9 @@ import org.apache.ranger.plugin.service.RangerBasePlugin; import org.apache.ranger.plugin.util.ServicePolicies; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.util.Set; import static com.google.common.net.HttpHeaders.AUTHORIZATION; @@ -53,6 +56,17 @@ public RangerAuthorizer(ServicePolicies servicePolicies) plugin.setPolicies(servicePolicies); } + private static T jsonParse(Response response, Class clazz) + throws IOException + { + BufferedReader bufferedReader = null; + if (response.body() != null) { + bufferedReader = new BufferedReader(new InputStreamReader(response.body().byteStream())); + } + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(bufferedReader, clazz); + } + public static Interceptor basicAuth(String user, String password) { requireNonNull(user, "user is null"); @@ -72,7 +86,7 @@ private static OkHttpClient getOkHttpAuthClient(String username, String password return builder.build(); } - public boolean authorizeHiveResource(String database, String table, String column, String accessType, String user, Set userGroups) + public boolean authorizeHiveResource(String database, String table, String column, String accessType, String user, Set userGroups, Set userRoles) { String keyDatabase = "database"; String keyTable = "table"; @@ -90,7 +104,7 @@ public boolean authorizeHiveResource(String database, String table, String colum resource.setValue(keyColumn, column); } - RangerAccessRequest request = new RangerAccessRequestImpl(resource, accessType.toLowerCase(ENGLISH), user, userGroups, null); + RangerAccessRequest request = new RangerAccessRequestImpl(resource, accessType.toLowerCase(ENGLISH), user, userGroups, userRoles); RangerAccessResult result = plugin.isAccessAllowed(request); return result != null && result.getIsAllowed(); } diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java index d2b94c052dbb4..6ea1e14dc236e 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControl.java @@ -31,6 +31,7 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; import org.apache.ranger.plugin.util.ServicePolicies; import org.jetbrains.annotations.TestOnly; @@ -40,14 +41,20 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import static com.facebook.airlift.json.JsonCodec.jsonCodec; import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_POLICY_MGR_DOWNLOAD_URL; import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_USER_GROUP_URL; +import static com.facebook.presto.hive.security.ranger.RangerBasedAccessControlConfig.RANGER_REST_USER_ROLES_URL; import static com.facebook.presto.spi.security.AccessDeniedException.denyAddColumn; +import static com.facebook.presto.spi.security.AccessDeniedException.denyCreateSchema; import static com.facebook.presto.spi.security.AccessDeniedException.denyCreateTable; import static com.facebook.presto.spi.security.AccessDeniedException.denyCreateView; import static com.facebook.presto.spi.security.AccessDeniedException.denyCreateViewWithSelect; @@ -59,7 +66,6 @@ import static com.facebook.presto.spi.security.AccessDeniedException.denyInsertTable; import static com.facebook.presto.spi.security.AccessDeniedException.denyRenameColumn; import static com.facebook.presto.spi.security.AccessDeniedException.denyRenameTable; -import static com.facebook.presto.spi.security.AccessDeniedException.denySelectColumns; import static com.google.common.net.HttpHeaders.AUTHORIZATION; import static java.lang.String.format; import static java.util.Objects.requireNonNull; @@ -75,6 +81,7 @@ public class RangerBasedAccessControl private RangerAuthorizer rangerAuthorizer; private Users users; + private static Map> userRolesMapping = new HashMap<>(); @TestOnly public RangerBasedAccessControl() @@ -87,7 +94,6 @@ public RangerBasedAccessControl(RangerBasedAccessControlConfig config) requireNonNull(config.getRangerHttpEndPoint(), "Ranger service http end point is null"); requireNonNull(config.getRangerHiveServiceName(), "Ranger hive service name is null"); - OkHttpClient httpClient = null; ServicePolicies servicePolicies; try { OkHttpClient client = getAuthHttpClient(config); @@ -104,6 +110,7 @@ public RangerBasedAccessControl(RangerBasedAccessControlConfig config) servicePolicies = getHiveServicePolicies(client, hiveServicePolicyUrl); users = getUsers(client, getUsersUrl); rangerAuthorizer = new RangerAuthorizer(servicePolicies); + userRolesMapping = getRolesForUserList(client, config.getRangerHttpEndPoint()); } catch (Exception e) { log.error("Exception while querying ranger service ", e); @@ -135,6 +142,31 @@ private Users getUsers(OkHttpClient client, HttpUrl endPtUri) return users.getValue(); } + private Map> getRolesForUserList(OkHttpClient client, String rangerEndPoint) + { + List usersList = users.getvXUsers().stream().map(VXUser::getName).collect(Collectors.toList()); + HttpUrl getRolesUrl; + for (String user : usersList) { + getRolesUrl = requireNonNull(HttpUrl.get(URI.create(rangerEndPoint))) + .newBuilder() + .encodedPath(RANGER_REST_USER_ROLES_URL + "/" + user) + .build(); + userRolesMapping.put(user, getRolesForUser(client, getRolesUrl)); + } + return userRolesMapping; + } + + private Set getRolesForUser(OkHttpClient client, HttpUrl endPtUri) + { + Request request = new Request.Builder().url(endPtUri).header("Accept", "application/json").build(); + JsonCodec rolesJsonCodec = jsonCodec(List.class); + JsonResponse roles = JsonResponse.execute(rolesJsonCodec, client, request); + if (!roles.hasValue()) { + throw new RuntimeException(format("Request to %s failed: %s [Error: %s]", endPtUri, roles, roles.getResponseBody())); + } + return new HashSet<>(roles.getValue()); + } + @TestOnly public void setRangerAuthorizer(RangerAuthorizer rangerAuthorizer) { @@ -147,6 +179,12 @@ public void setUsers(Users users) this.users = users; } + @TestOnly + public void setUserRoles(Map> userRolesMapping) + { + this.userRolesMapping = userRolesMapping; + } + private static T jsonParse(Response response, Class clazz) throws IOException { @@ -186,7 +224,7 @@ enum HiveAccessType private boolean checkAccess(ConnectorIdentity identity, SchemaTableName tableName, String column, HiveAccessType accessType) { return rangerAuthorizer.authorizeHiveResource(tableName.getSchemaName(), tableName.getTableName(), column, - accessType.toString(), identity.getUser(), getGroupsForUser(identity.getUser())); + accessType.toString(), identity.getUser(), getGroupsForUser(identity.getUser()), userRolesMapping.get(identity.getUser())); } /** @@ -196,6 +234,11 @@ private boolean checkAccess(ConnectorIdentity identity, SchemaTableName tableNam */ public void checkCanCreateSchema(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, String schemaName) { + if (!rangerAuthorizer.authorizeHiveResource(schemaName, null, null, + HiveAccessType.CREATE.toString(), identity.getUser(), getGroupsForUser(identity.getUser()), userRolesMapping.get(identity.getUser()))) { + denyCreateSchema(schemaName, format("Access denied - User [ %s ] does not have [CREATE] " + + "privilege on [ %s ] ", identity.getUser(), schemaName)); + } } /** @@ -205,8 +248,8 @@ public void checkCanCreateSchema(ConnectorTransactionHandle transactionHandle, C */ public void checkCanDropSchema(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, AccessControlContext context, String schemaName) { - SchemaTableName schemaTableName = new SchemaTableName(schemaName, schemaName); - if (!checkAccess(identity, schemaTableName, null, HiveAccessType.DROP)) { + if (!rangerAuthorizer.authorizeHiveResource(schemaName, null, null, + HiveAccessType.DROP.toString(), identity.getUser(), getGroupsForUser(identity.getUser()), userRolesMapping.get(identity.getUser()))) { denyDropSchema(schemaName, format("Access denied - User [ %s ] does not have [DROP] " + "privilege on [ %s ] ", identity.getUser(), schemaName)); } @@ -234,9 +277,10 @@ public Set filterSchemas(ConnectorTransactionHandle transactionHandle, C { Set allowedSchemas = new HashSet<>(); Set groups = getGroupsForUser(identity.getUser()); + Set roles = userRolesMapping.get(identity.getUser()); for (String schema : schemaNames) { - if (rangerAuthorizer.authorizeHiveResource(schema, null, null, HiveAccessType.SELECT.toString(), identity.getUser(), groups)) { + if (rangerAuthorizer.authorizeHiveResource(schema, null, null, RangerPolicyEngine.ANY_ACCESS, identity.getUser(), groups, roles)) { allowedSchemas.add(schema); } } @@ -265,9 +309,10 @@ public Set filterTables(ConnectorTransactionHandle transactionH { Set allowedTables = new HashSet<>(); Set groups = getGroupsForUser(identity.getUser()); + Set roles = userRolesMapping.get(identity.getUser()); for (SchemaTableName table : tableNames) { - if (rangerAuthorizer.authorizeHiveResource(table.getSchemaName(), table.getTableName(), null, HiveAccessType.SELECT.toString(), identity.getUser(), groups)) { + if (rangerAuthorizer.authorizeHiveResource(table.getSchemaName(), table.getTableName(), null, RangerPolicyEngine.ANY_ACCESS, identity.getUser(), groups, roles)) { allowedTables.add(table); } } @@ -331,8 +376,8 @@ public void checkCanSelectFromColumns(ConnectorTransactionHandle transactionHand } } if (deniedColumns.size() > 0) { - denySelectColumns(tableName.getTableName(), columnNames, format("Access denied - User [ %s ] does not have [SELECT] " + - "privilege on all mentioned columns of [ %s/%s ] ", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); + throw new AccessDeniedException(format("User [ %s ] does not have [SELECT] " + + "privilege on all mentioned columns of [ %s/%s ]", identity.getUser(), tableName.getSchemaName(), tableName.getTableName())); } } diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java index c4026027f0f84..9158ef40ca563 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/security/ranger/RangerBasedAccessControlConfig.java @@ -31,6 +31,7 @@ public class RangerBasedAccessControlConfig public static final String RANGER_REST_POLICY_MGR_DOWNLOAD_URL = "/service/plugins/policies/download"; public static final String RANGER_REST_USER_GROUP_URL = "/service/xusers/users"; + public static final String RANGER_REST_USER_ROLES_URL = "/service/roles/roles/user"; public static final String RANGER_REST_POLICY_MGR_KEYSTORE_PATH = "hive.ranger.service.keystore.path"; public static final String RANGER_REST_POLICY_MGR_KEYSTORE_PWD = "hive.ranger.service.keystore.password"; diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java index 859fdf6297cd9..c5a00012deaa6 100644 --- a/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java +++ b/presto-hive/src/test/java/com/facebook/presto/hive/security/ranger/TestRangerBasedAccessControl.java @@ -34,7 +34,13 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; import static org.testng.Assert.assertThrows; @@ -47,12 +53,12 @@ public class TestRangerBasedAccessControl public void testTablePriviledgesRolesNotAllowed() throws IOException { - ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json"); + ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json", "user_roles.json"); assertDenied(() -> accessControl.checkCanRevokeTablePrivilege(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, Privilege.SELECT, new SchemaTableName("foodmart", "test"), new PrestoPrincipal(PrincipalType.ROLE, "role"), true)); assertDenied(() -> accessControl.checkCanGrantTablePrivilege(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, Privilege.SELECT, new SchemaTableName("foodmart", "test"), new PrestoPrincipal(PrincipalType.ROLE, "role"), true)); - assertDenied(() -> accessControl.checkCanCreateRole(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName", null)); + assertDenied(() -> accessControl.checkCanCreateRole(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName", Optional.empty())); assertDenied(() -> accessControl.checkCanDropRole(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName")); assertDenied(() -> accessControl.checkCanGrantRoles(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, ImmutableSet.of(""), ImmutableSet.of(new PrestoPrincipal(PrincipalType.ROLE, "role")), true, Optional.empty(), "")); @@ -63,7 +69,7 @@ public void testTablePriviledgesRolesNotAllowed() public void testDefaultAccessAllowedNotChecked() throws IOException { - ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json"); + ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json", "user_roles.json"); accessControl.checkCanShowTablesMetadata(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName"); accessControl.checkCanSetCatalogSessionProperty(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName"); accessControl.checkCanCreateSchema(TRANSACTION_HANDLE, user("anyuser"), CONTEXT, "schemaName"); @@ -74,7 +80,7 @@ public void testDefaultAccessAllowedNotChecked() public void testDefaultTableAccessIfNotDefined() throws IOException { - ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json"); + ConnectorAccessControl accessControl = createRangerAccessControl("default-allow-all.json", "user_groups.json", "user_roles.json"); accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("admin"), CONTEXT, new SchemaTableName("test", "test")); accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("test", "test"), ImmutableSet.of()); accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("bobschema", "bobtable"), ImmutableSet.of()); @@ -88,7 +94,7 @@ public void testDefaultTableAccessIfNotDefined() public void testTableOperations() throws IOException { - ConnectorAccessControl accessControl = createRangerAccessControl("default-schema-level-access.json", "user_groups.json"); + ConnectorAccessControl accessControl = createRangerAccessControl("default-schema-level-access.json", "user_groups.json", "user_roles.json"); // 'etladmin' group have all access {group - etladmin, user - alice} accessControl.checkCanCreateTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); accessControl.checkCanRenameTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"), new SchemaTableName("foodmart", "test1")); @@ -121,7 +127,7 @@ public void testTableOperations() public void testSelectUpdateAccess() throws IOException { - ConnectorAccessControl accessControl = createRangerAccessControl("default-table-select-update.json", "user_groups.json"); + ConnectorAccessControl accessControl = createRangerAccessControl("default-table-select-update.json", "user_groups.json", "user_roles.json"); // 'etladmin' group have all access {group - etladmin, user - alice} accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test"), ImmutableSet.of("column1")); accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("alice"), CONTEXT, new SchemaTableName("foodmart", "test")); @@ -139,7 +145,7 @@ public void testSelectUpdateAccess() public void testColumnLevelAccess() throws IOException { - ConnectorAccessControl accessControl = createRangerAccessControl("default-table-column-access.json", "user_groups.json"); + ConnectorAccessControl accessControl = createRangerAccessControl("default-table-column-access.json", "user_groups.json", "user_roles.json"); // 'analyst' group have read acces {group - analyst, user - joe} accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("joe"), CONTEXT, new SchemaTableName("foodmart", "salary"), ImmutableSet.of("currency_id", "overtime_paid")); @@ -147,23 +153,59 @@ public void testColumnLevelAccess() assertDenied(() -> accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("bob"), CONTEXT, new SchemaTableName("foodmart", "salary"), ImmutableSet.of("currency_id", "overtime_paid"))); } + @Test + public void testRoleBasedAccess() + throws IOException + { + ConnectorAccessControl accessControl = createRangerAccessControl("ranger-role-based-access.json", "user_groups.json", "user_roles.json"); + + // 'admin_role' role have all access {user - raj, group - admin, role - admin_role} + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("raj"), CONTEXT, new SchemaTableName("default", "customer"), ImmutableSet.of("column1")); + accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("raj"), CONTEXT, new SchemaTableName("default", "customer")); + accessControl.checkCanDropTable(TRANSACTION_HANDLE, user("raj"), CONTEXT, new SchemaTableName("default", "customer")); + + // 'etl_role' role have all access {user - maria, group - etldev, role - etl_role} + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("maria"), CONTEXT, new SchemaTableName("default", "orders"), ImmutableSet.of("column1")); + accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("maria"), CONTEXT, new SchemaTableName("default", "orders")); + accessControl.checkCanDropTable(TRANSACTION_HANDLE, user("maria"), CONTEXT, new SchemaTableName("default", "orders")); + // Access denied to columns other than name & comment {user - maria, group - etldev, role - etl_role} + assertDenied(() -> accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("maria"), CONTEXT, new SchemaTableName("default", "customer"), ImmutableSet.of("column1"))); + + // 'analyst_role' role have all access {user - sam, group - analyst, role - analyst_role} + accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("sam"), CONTEXT, new SchemaTableName("default", "lineitem"), ImmutableSet.of("column1")); + accessControl.checkCanInsertIntoTable(TRANSACTION_HANDLE, user("sam"), CONTEXT, new SchemaTableName("default", "lineitem")); + accessControl.checkCanDropTable(TRANSACTION_HANDLE, user("sam"), CONTEXT, new SchemaTableName("default", "lineitem")); + // Access denied {user - sam, group - analyst, role - analyst_role} + assertDenied(() -> accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("sam"), CONTEXT, new SchemaTableName("default", "customer"), ImmutableSet.of("column1"))); + assertDenied(() -> accessControl.checkCanSelectFromColumns(TRANSACTION_HANDLE, user("sam"), CONTEXT, new SchemaTableName("default", "supplier"), ImmutableSet.of("column1"))); + } + private static ConnectorIdentity user(String name) { return new ConnectorIdentity(name, Optional.empty(), Optional.empty()); } - private ConnectorAccessControl createRangerAccessControl(String policyFile, String usersFile) + private ConnectorAccessControl createRangerAccessControl(String policyFile, String usersFile, String rolesFile) throws IOException { String policyFilePath = this.getClass().getClassLoader().getResource("com.facebook.presto.hive.security.ranger/" + policyFile).getPath(); String usersFilePath = this.getClass().getClassLoader().getResource("com.facebook.presto.hive.security.ranger/" + usersFile).getPath(); + String rolesFilePath = this.getClass().getClassLoader().getResource("com.facebook.presto.hive.security.ranger/" + rolesFile).getPath(); ServicePolicies servicePolicies = jsonParse(new File(policyFilePath), ServicePolicies.class); Users users = jsonParse(new File(usersFilePath), Users.class); + HashMap> userRoles = Arrays.stream(jsonParse(new File(rolesFilePath), HashMap[].class)).findFirst().get(); + + Map> userRolesSet = + userRoles.entrySet().stream().collect(Collectors.toMap( + entry -> entry.getKey(), + entry -> new HashSet(entry.getValue()))); + RangerBasedAccessControl rangerBasedAccessControl = new RangerBasedAccessControl(); RangerAuthorizer rangerAuthorizer = new RangerAuthorizer(servicePolicies); rangerBasedAccessControl.setRangerAuthorizer(rangerAuthorizer); rangerBasedAccessControl.setUsers(users); + rangerBasedAccessControl.setUserRoles(userRolesSet); return rangerBasedAccessControl; } diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/ranger-role-based-access.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/ranger-role-based-access.json new file mode 100644 index 0000000000000..a41422885b241 --- /dev/null +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/ranger-role-based-access.json @@ -0,0 +1,1566 @@ +{ + "serviceName": "hivedev", + "serviceId": 1, + "policyVersion": 60, + "policyUpdateTime": 1624521930000, + "policies": [ + { + "id": 1, + "guid": "30748e19-d0ce-4f99-8df3-0dc108c816a3", + "isEnabled": true, + "version": 10, + "service": "hivedev", + "name": "all - database", + "policyType": 0, + "policyPriority": 0, + "description": "Policy for all - database", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + }, + { + "type": "update", + "isAllowed": true + }, + { + "type": "create", + "isAllowed": true + }, + { + "type": "drop", + "isAllowed": true + }, + { + "type": "alter", + "isAllowed": true + }, + { + "type": "index", + "isAllowed": true + }, + { + "type": "lock", + "isAllowed": true + }, + { + "type": "all", + "isAllowed": true + }, + { + "type": "read", + "isAllowed": true + }, + { + "type": "write", + "isAllowed": true + }, + { + "type": "repladmin", + "isAllowed": true + }, + { + "type": "serviceadmin", + "isAllowed": true + }, + { + "type": "tempudfadmin", + "isAllowed": true + }, + { + "type": "refresh", + "isAllowed": true + } + ], + "users": [ + "ranger" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + }, + { + "accesses": [ + { + "type": "all", + "isAllowed": true + } + ], + "users": [ + "{OWNER}" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + }, + { + "accesses": [ + { + "type": "create", + "isAllowed": true + } + ], + "users": [], + "groups": [ + "public" + ], + "roles": [], + "conditions": [], + "delegateAdmin": false + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 2, + "guid": "685af250-c681-458f-9b0e-ce102037808b", + "isEnabled": true, + "version": 1, + "service": "hivedev", + "name": "all - hiveservice", + "policyType": 0, + "policyPriority": 0, + "description": "Policy for all - hiveservice", + "isAuditEnabled": true, + "resources": { + "hiveservice": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + }, + { + "type": "update", + "isAllowed": true + }, + { + "type": "create", + "isAllowed": true + }, + { + "type": "drop", + "isAllowed": true + }, + { + "type": "alter", + "isAllowed": true + }, + { + "type": "index", + "isAllowed": true + }, + { + "type": "lock", + "isAllowed": true + }, + { + "type": "all", + "isAllowed": true + }, + { + "type": "read", + "isAllowed": true + }, + { + "type": "write", + "isAllowed": true + }, + { + "type": "repladmin", + "isAllowed": true + }, + { + "type": "serviceadmin", + "isAllowed": true + }, + { + "type": "tempudfadmin", + "isAllowed": true + }, + { + "type": "refresh", + "isAllowed": true + } + ], + "users": [ + "ranger" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 3, + "guid": "5935e338-3c0b-42df-b38c-5679cc8de1c8", + "isEnabled": true, + "version": 3, + "service": "hivedev", + "name": "all - database, table, column", + "policyType": 0, + "policyPriority": 0, + "description": "Policy for all - database, table, column", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "column": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "table": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + }, + { + "type": "update", + "isAllowed": true + }, + { + "type": "create", + "isAllowed": true + }, + { + "type": "drop", + "isAllowed": true + }, + { + "type": "alter", + "isAllowed": true + }, + { + "type": "index", + "isAllowed": true + }, + { + "type": "lock", + "isAllowed": true + }, + { + "type": "all", + "isAllowed": true + }, + { + "type": "read", + "isAllowed": true + }, + { + "type": "write", + "isAllowed": true + }, + { + "type": "repladmin", + "isAllowed": true + }, + { + "type": "serviceadmin", + "isAllowed": true + }, + { + "type": "tempudfadmin", + "isAllowed": true + }, + { + "type": "refresh", + "isAllowed": true + } + ], + "users": [ + "ranger" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + }, + { + "accesses": [ + { + "type": "all", + "isAllowed": true + } + ], + "users": [ + "{OWNER}" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 4, + "guid": "9712d3c6-12df-4576-a4ef-3b81f7e0fcbe", + "isEnabled": true, + "version": 1, + "service": "hivedev", + "name": "all - database, table", + "policyType": 0, + "policyPriority": 0, + "description": "Policy for all - database, table", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "table": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + }, + { + "type": "update", + "isAllowed": true + }, + { + "type": "create", + "isAllowed": true + }, + { + "type": "drop", + "isAllowed": true + }, + { + "type": "alter", + "isAllowed": true + }, + { + "type": "index", + "isAllowed": true + }, + { + "type": "lock", + "isAllowed": true + }, + { + "type": "all", + "isAllowed": true + }, + { + "type": "read", + "isAllowed": true + }, + { + "type": "write", + "isAllowed": true + }, + { + "type": "repladmin", + "isAllowed": true + }, + { + "type": "serviceadmin", + "isAllowed": true + }, + { + "type": "tempudfadmin", + "isAllowed": true + }, + { + "type": "refresh", + "isAllowed": true + } + ], + "users": [ + "ranger" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + }, + { + "accesses": [ + { + "type": "all", + "isAllowed": true + } + ], + "users": [ + "{OWNER}" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 5, + "guid": "65b3e31e-234d-4eb7-83f1-d45c26bab1b7", + "isEnabled": true, + "version": 1, + "service": "hivedev", + "name": "all - database, udf", + "policyType": 0, + "policyPriority": 0, + "description": "Policy for all - database, udf", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "udf": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + }, + { + "type": "update", + "isAllowed": true + }, + { + "type": "create", + "isAllowed": true + }, + { + "type": "drop", + "isAllowed": true + }, + { + "type": "alter", + "isAllowed": true + }, + { + "type": "index", + "isAllowed": true + }, + { + "type": "lock", + "isAllowed": true + }, + { + "type": "all", + "isAllowed": true + }, + { + "type": "read", + "isAllowed": true + }, + { + "type": "write", + "isAllowed": true + }, + { + "type": "repladmin", + "isAllowed": true + }, + { + "type": "serviceadmin", + "isAllowed": true + }, + { + "type": "tempudfadmin", + "isAllowed": true + }, + { + "type": "refresh", + "isAllowed": true + } + ], + "users": [ + "ranger" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + }, + { + "accesses": [ + { + "type": "all", + "isAllowed": true + } + ], + "users": [ + "{OWNER}" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 6, + "guid": "5751aaba-3f32-4dbc-b450-8999221aee04", + "isEnabled": true, + "version": 1, + "service": "hivedev", + "name": "all - url", + "policyType": 0, + "policyPriority": 0, + "description": "Policy for all - url", + "isAuditEnabled": true, + "resources": { + "url": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": true + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + }, + { + "type": "update", + "isAllowed": true + }, + { + "type": "create", + "isAllowed": true + }, + { + "type": "drop", + "isAllowed": true + }, + { + "type": "alter", + "isAllowed": true + }, + { + "type": "index", + "isAllowed": true + }, + { + "type": "lock", + "isAllowed": true + }, + { + "type": "all", + "isAllowed": true + }, + { + "type": "read", + "isAllowed": true + }, + { + "type": "write", + "isAllowed": true + }, + { + "type": "repladmin", + "isAllowed": true + }, + { + "type": "serviceadmin", + "isAllowed": true + }, + { + "type": "tempudfadmin", + "isAllowed": true + }, + { + "type": "refresh", + "isAllowed": true + } + ], + "users": [ + "ranger" + ], + "groups": [], + "roles": [], + "conditions": [], + "delegateAdmin": true + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 7, + "guid": "36ab0bdf-83c0-4f58-b056-cbbe8fd215c1", + "isEnabled": true, + "version": 10, + "service": "hivedev", + "name": "default database tables columns", + "policyType": 0, + "policyPriority": 0, + "description": "", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "default" + ], + "isExcludes": false, + "isRecursive": false + }, + "column": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "table": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "all", + "isAllowed": true + } + ], + "users": [], + "groups": [], + "roles": [ + "admin_role" + ], + "conditions": [], + "delegateAdmin": false + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 8, + "guid": "d385b4dd-ce10-4ec3-a9ed-814b7b952399", + "isEnabled": true, + "version": 1, + "service": "hivedev", + "name": "Information_schema database tables columns", + "policyType": 0, + "policyPriority": 0, + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "information_schema" + ], + "isExcludes": false, + "isRecursive": false + }, + "column": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "table": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + } + ], + "users": [], + "groups": [ + "public" + ], + "roles": [], + "conditions": [], + "delegateAdmin": false + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 10, + "guid": "97f4c9c8-b851-48d7-8b19-5dec3b8873b1", + "isEnabled": true, + "version": 8, + "service": "hivedev", + "name": "default ETL", + "policyType": 0, + "policyPriority": 0, + "description": "", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "default" + ], + "isExcludes": false, + "isRecursive": false + }, + "column": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "table": { + "values": [ + "orders", + "lineitem", + "supplier" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "all", + "isAllowed": true + } + ], + "users": [], + "groups": [], + "roles": [ + "etl_role" + ], + "conditions": [], + "delegateAdmin": false + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 11, + "guid": "1ece0d35-64de-4128-a7f2-fb0365d947e9", + "isEnabled": true, + "version": 6, + "service": "hivedev", + "name": "default Analyst", + "policyType": 0, + "policyPriority": 0, + "description": "", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "default" + ], + "isExcludes": false, + "isRecursive": false + }, + "column": { + "values": [ + "*" + ], + "isExcludes": false, + "isRecursive": false + }, + "table": { + "values": [ + "lineitem", + "orders" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "all", + "isAllowed": true + } + ], + "users": [], + "groups": [], + "roles": [ + "analyst_role" + ], + "conditions": [], + "delegateAdmin": false + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + }, + { + "id": 12, + "guid": "e443ba2b-cf9c-4d46-806e-22705fc32e93", + "isEnabled": true, + "version": 5, + "service": "hivedev", + "name": "customer table", + "policyType": 0, + "policyPriority": 0, + "description": "", + "isAuditEnabled": true, + "resources": { + "database": { + "values": [ + "default" + ], + "isExcludes": false, + "isRecursive": false + }, + "column": { + "values": [ + "name", + "comment" + ], + "isExcludes": false, + "isRecursive": false + }, + "table": { + "values": [ + "customer" + ], + "isExcludes": false, + "isRecursive": false + } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "select", + "isAllowed": true + } + ], + "users": [], + "groups": [], + "roles": [ + "etl_role" + ], + "conditions": [], + "delegateAdmin": false + } + ], + "denyPolicyItems": [], + "allowExceptions": [], + "denyExceptions": [], + "dataMaskPolicyItems": [], + "rowFilterPolicyItems": [], + "serviceType": "hive", + "options": {}, + "validitySchedules": [], + "policyLabels": [], + "zoneName": "", + "isDenyAllElse": false + } + ], + "serviceDef": { + "id": 3, + "guid": "3e1afb5a-184a-4e82-9d9c-87a5cacc243c", + "isEnabled": true, + "createTime": 1611205297000, + "updateTime": 1611205297000, + "version": 1, + "name": "hive", + "displayName": "Hadoop SQL", + "implClass": "org.apache.ranger.services.hive.RangerServiceHive", + "label": "Hive Server2", + "description": "Hive Server2", + "options": { + "enableDenyAndExceptionsInPolicies": "true" + }, + "configs": [ + { + "itemId": 1, + "name": "username", + "type": "string", + "mandatory": true, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Username" + }, + { + "itemId": 2, + "name": "password", + "type": "password", + "mandatory": true, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Password" + }, + { + "itemId": 3, + "name": "jdbc.driverClassName", + "type": "string", + "mandatory": true, + "defaultValue": "org.apache.hive.jdbc.HiveDriver", + "validationRegEx": "", + "validationMessage": "", + "uiHint": "" + }, + { + "itemId": 4, + "name": "jdbc.url", + "type": "string", + "mandatory": true, + "defaultValue": "", + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{\"TextFieldWithIcon\":true, \"info\": \"1.For Remote Mode, eg.
jdbc:hive2://<host>:<port>
2.For Embedded Mode (no host or port), eg.
jdbc:hive2:///;initFile=<file>
3.For HTTP Mode, eg.
jdbc:hive2://<host>:<port>/;
transportMode=http;httpPath=<httpPath>
4.For SSL Mode, eg.
jdbc:hive2://<host>:<port>/;ssl=true;
sslTrustStore=tStore;trustStorePassword=pw
5.For ZooKeeper Mode, eg.
jdbc:hive2://<host>/;serviceDiscoveryMode=
zooKeeper;zooKeeperNamespace=hiveserver2
6.For Kerberos Mode, eg.
jdbc:hive2://<host>:<port>/;
principal=hive/domain@EXAMPLE.COM
\"}" + }, + { + "itemId": 5, + "name": "commonNameForCertificate", + "type": "string", + "mandatory": false, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Common Name for Certificate" + } + ], + "resources": [ + { + "itemId": 1, + "name": "database", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Hive Database", + "description": "Hive Database", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 5, + "name": "url", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": true, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerURLResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "URL", + "description": "URL", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 6, + "name": "hiveservice", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Hive Service", + "description": "Hive Service", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 7, + "name": "global", + "type": "string", + "level": 10, + "mandatory": false, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Global", + "description": "Global", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 2, + "name": "table", + "type": "string", + "level": 20, + "parent": "database", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Hive Table", + "description": "Hive Table", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 3, + "name": "udf", + "type": "string", + "level": 20, + "parent": "database", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Hive UDF", + "description": "Hive UDF", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 4, + "name": "column", + "type": "string", + "level": 30, + "parent": "table", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Hive Column", + "description": "Hive Column", + "accessTypeRestrictions": [], + "isValidLeaf": true + } + ], + "accessTypes": [ + { + "itemId": 1, + "name": "select", + "label": "select", + "impliedGrants": [] + }, + { + "itemId": 2, + "name": "update", + "label": "update", + "impliedGrants": [] + }, + { + "itemId": 3, + "name": "create", + "label": "Create", + "impliedGrants": [] + }, + { + "itemId": 4, + "name": "drop", + "label": "Drop", + "impliedGrants": [] + }, + { + "itemId": 5, + "name": "alter", + "label": "Alter", + "impliedGrants": [] + }, + { + "itemId": 6, + "name": "index", + "label": "Index", + "impliedGrants": [] + }, + { + "itemId": 7, + "name": "lock", + "label": "Lock", + "impliedGrants": [] + }, + { + "itemId": 8, + "name": "all", + "label": "All", + "impliedGrants": [ + "select", + "update", + "create", + "drop", + "alter", + "index", + "lock", + "read", + "write", + "repladmin", + "serviceadmin", + "refresh" + ] + }, + { + "itemId": 9, + "name": "read", + "label": "Read", + "impliedGrants": [] + }, + { + "itemId": 10, + "name": "write", + "label": "Write", + "impliedGrants": [] + }, + { + "itemId": 11, + "name": "repladmin", + "label": "ReplAdmin", + "impliedGrants": [] + }, + { + "itemId": 12, + "name": "serviceadmin", + "label": "Service Admin", + "impliedGrants": [] + }, + { + "itemId": 13, + "name": "tempudfadmin", + "label": "Temporary UDF Admin", + "impliedGrants": [] + }, + { + "itemId": 14, + "name": "refresh", + "label": "Refresh", + "impliedGrants": [] + } + ], + "policyConditions": [], + "contextEnrichers": [], + "enums": [], + "dataMaskDef": { + "maskTypes": [ + { + "itemId": 1, + "name": "MASK", + "label": "Redact", + "description": "Replace lowercase with 'x', uppercase with 'X', digits with '0'", + "transformer": "mask({col})", + "dataMaskOptions": {} + }, + { + "itemId": 2, + "name": "MASK_SHOW_LAST_4", + "label": "Partial mask: show last 4", + "description": "Show last 4 characters; replace rest with 'x'", + "transformer": "mask_show_last_n({col}, 4, 'x', 'x', 'x', -1, '1')", + "dataMaskOptions": {} + }, + { + "itemId": 3, + "name": "MASK_SHOW_FIRST_4", + "label": "Partial mask: show first 4", + "description": "Show first 4 characters; replace rest with 'x'", + "transformer": "mask_show_first_n({col}, 4, 'x', 'x', 'x', -1, '1')", + "dataMaskOptions": {} + }, + { + "itemId": 4, + "name": "MASK_HASH", + "label": "Hash", + "description": "Hash the value", + "transformer": "mask_hash({col})", + "dataMaskOptions": {} + }, + { + "itemId": 5, + "name": "MASK_NULL", + "label": "Nullify", + "description": "Replace with NULL", + "dataMaskOptions": {} + }, + { + "itemId": 6, + "name": "MASK_NONE", + "label": "Unmasked (retain original value)", + "description": "No masking", + "dataMaskOptions": {} + }, + { + "itemId": 12, + "name": "MASK_DATE_SHOW_YEAR", + "label": "Date: show only year", + "description": "Date: show only year", + "transformer": "mask({col}, 'x', 'x', 'x', -1, '1', 1, 0, -1)", + "dataMaskOptions": {} + }, + { + "itemId": 13, + "name": "CUSTOM", + "label": "Custom", + "description": "Custom", + "dataMaskOptions": {} + } + ], + "accessTypes": [ + { + "itemId": 1, + "name": "select", + "label": "select", + "impliedGrants": [] + } + ], + "resources": [ + { + "itemId": 1, + "name": "database", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "false", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{ \"singleValue\":true }", + "label": "Hive Database", + "description": "Hive Database", + "accessTypeRestrictions": [], + "isValidLeaf": false + }, + { + "itemId": 2, + "name": "table", + "type": "string", + "level": 20, + "parent": "database", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "false", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{ \"singleValue\":true }", + "label": "Hive Table", + "description": "Hive Table", + "accessTypeRestrictions": [], + "isValidLeaf": false + }, + { + "itemId": 4, + "name": "column", + "type": "string", + "level": 30, + "parent": "table", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "false", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{ \"singleValue\":true }", + "label": "Hive Column", + "description": "Hive Column", + "accessTypeRestrictions": [], + "isValidLeaf": true + } + ] + }, + "rowFilterDef": { + "accessTypes": [ + { + "itemId": 1, + "name": "select", + "label": "select", + "impliedGrants": [] + } + ], + "resources": [ + { + "itemId": 1, + "name": "database", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "false", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{ \"singleValue\":true }", + "label": "Hive Database", + "description": "Hive Database", + "accessTypeRestrictions": [], + "isValidLeaf": false + }, + { + "itemId": 2, + "name": "table", + "type": "string", + "level": 20, + "parent": "database", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "false", + "ignoreCase": "true" + }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{ \"singleValue\":true }", + "label": "Hive Table", + "description": "Hive Table", + "accessTypeRestrictions": [], + "isValidLeaf": true + } + ] + } + }, + "auditMode": "audit-default", + "serviceConfig": {} +} diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json index d8e41edbebe05..52b3c3a223b09 100644 --- a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_groups.json @@ -82,6 +82,78 @@ "ROLE_USER" ], "userSource": 1 + }, + { + "createDate": "2018-06-18T15:58:00Z", + "description": "raj - add from Unix box", + "firstName": "raj", + "groupIdList": [ + 2 + ], + "groupNameList": [ + "admin" + ], + "id": 11, + "isVisible": 1, + "lastName": "raj", + "name": "raj", + "owner": "Admin", + "password": "*****", + "status": 1, + "updateDate": "2020-10-13T10:03:10Z", + "updatedBy": "Admin", + "userRoleList": [ + "ROLE_USER" + ], + "userSource": 1 + }, + { + "createDate": "2018-06-18T15:58:00Z", + "description": "maria - add from Unix box", + "firstName": "Maria", + "groupIdList": [ + 3 + ], + "groupNameList": [ + "etldev" + ], + "id": 12, + "isVisible": 1, + "lastName": "maria", + "name": "maria", + "owner": "Admin", + "password": "*****", + "status": 1, + "updateDate": "2020-10-13T10:03:10Z", + "updatedBy": "Admin", + "userRoleList": [ + "ROLE_USER" + ], + "userSource": 1 + }, + { + "createDate": "2018-06-18T15:58:00Z", + "description": "sam - add from Unix box", + "firstName": "Sam", + "groupIdList": [ + 4 + ], + "groupNameList": [ + "analyst" + ], + "id": 13, + "isVisible": 1, + "lastName": "sam", + "name": "sam", + "owner": "Admin", + "password": "*****", + "status": 1, + "updateDate": "2020-10-13T10:03:10Z", + "updatedBy": "Admin", + "userRoleList": [ + "ROLE_USER" + ], + "userSource": 1 } ] } diff --git a/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_roles.json b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_roles.json new file mode 100644 index 0000000000000..1d839be925e06 --- /dev/null +++ b/presto-hive/src/test/resources/com.facebook.presto.hive.security.ranger/user_roles.json @@ -0,0 +1,14 @@ +[ + { + "admin": [], + "raj": [ + "admin_role" + ], + "maria": [ + "etl_role" + ], + "sam": [ + "analyst_role" + ] + } +] From 6c9cb687c56850d0024e7ccdf6996d732c38921d Mon Sep 17 00:00:00 2001 From: Ashish Tadose Date: Mon, 28 Jun 2021 17:02:20 +0530 Subject: [PATCH 5/5] Doc update --- .../src/main/sphinx/connector/hive-security.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/presto-docs/src/main/sphinx/connector/hive-security.rst b/presto-docs/src/main/sphinx/connector/hive-security.rst index 9bfa8db2ccf17..f681561190bcf 100644 --- a/presto-docs/src/main/sphinx/connector/hive-security.rst +++ b/presto-docs/src/main/sphinx/connector/hive-security.rst @@ -561,7 +561,7 @@ verify the following prerequisites: Presto coordinator and workers have the appropriate network access to communicate with the Ranger service. Typically this is port 6080. -Apache Ranger 0.7.0 or higher must be used +Apache Ranger 2.1.0 or higher must be used Policies -------- @@ -605,6 +605,15 @@ Property Name Description ``hive.ranger.service.basic-auth-password`` Ranger Hive plugin password configured with for Basic HTTP auth. + +``hive.ranger.service.keystore.path`` Ranger SSL configuration - client keystore file path + +``hive.ranger.service.keystore.password`` Ranger SSL configuration - client keystore password + +``hive.ranger.service.truststore.path`` Ranger SSL configuration - client trust-store file path + +``hive.ranger.service.truststore.password`` Ranger SSL configuration - client trust-store password + ================================================== ============================================================ ============ HDFS wire encryption