You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by me...@apache.org on 2019/05/20 13:27:11 UTC
[ranger] branch master updated: RANGER-2395 : Add Presto plugin,
This implements a plugin for Presto, a distributed SQL engine.
This is an automated email from the ASF dual-hosted git repository.
mehul pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new 43757e7 RANGER-2395 : Add Presto plugin, This implements a plugin for Presto, a distributed SQL engine.
43757e7 is described below
commit 43757e798751ffab99dbe15ab3f9ae0773ae69f7
Author: Bolke de Bruin <bo...@xs4all.nl>
AuthorDate: Mon May 6 20:00:53 2019 +0200
RANGER-2395 : Add Presto plugin, This implements a plugin for Presto, a distributed SQL engine.
Signed-off-by: Mehul Parikh <me...@apache.org>
---
agents-common/scripts/enable-agent.sh | 31 ++
.../plugin/store/EmbeddedServiceDefsUtil.java | 8 +-
.../service-defs/ranger-servicedef-presto.json | 197 ++++++++
.../conf/ranger-policymgr-ssl-changes.cfg | 21 +
plugin-presto/conf/ranger-policymgr-ssl.xml | 49 ++
plugin-presto/conf/ranger-presto-audit-changes.cfg | 58 +++
plugin-presto/conf/ranger-presto-audit.xml | 271 ++++++++++
.../conf/ranger-presto-security-changes.cfg | 28 ++
plugin-presto/conf/ranger-presto-security.xml | 74 +++
plugin-presto/pom.xml | 56 +++
plugin-presto/scripts/install.properties | 140 ++++++
.../authorizer/RangerSystemAccessControl.java | 459 +++++++++++++++++
.../services/presto/RangerServicePresto.java | 86 ++++
.../services/presto/client/PrestoClient.java | 556 +++++++++++++++++++++
.../presto/client/PrestoConnectionManager.java | 93 ++++
.../presto/client/PrestoResourceManager.java | 178 +++++++
pom.xml | 40 ++
ranger-presto-plugin-shim/pom.xml | 105 ++++
.../presto/authorizer/PrestoRangerPlugin.java | 32 ++
.../presto/authorizer/RangerConfig.java | 47 ++
.../authorizer/RangerSystemAccessControl.java | 382 ++++++++++++++
.../RangerSystemAccessControlFactory.java | 61 +++
.../META-INF/services/io.prestosql.spi.Plugin | 15 +
src/main/assembly/admin-web.xml | 21 +
src/main/assembly/plugin-presto.xml | 202 ++++++++
25 files changed, 3209 insertions(+), 1 deletion(-)
diff --git a/agents-common/scripts/enable-agent.sh b/agents-common/scripts/enable-agent.sh
index b4194a7..7dec0b1 100755
--- a/agents-common/scripts/enable-agent.sh
+++ b/agents-common/scripts/enable-agent.sh
@@ -212,6 +212,12 @@ elif [ "${HCOMPONENT_NAME}" = "kylin" ]; then
HCOMPONENT_LIB_DIR=${HCOMPONENT_INSTALL_DIR}/tomcat/webapps/kylin/WEB-INF/lib
elif [ "${HCOMPONENT_NAME}" = "elasticsearch" ]; then
HCOMPONENT_LIB_DIR=${HCOMPONENT_INSTALL_DIR}/plugins
+elif [ "${HCOMPONENT_NAME}" = "presto" ]; then
+ HCOMPONENT_LIB_DIR=${HCOMPONENT_INSTALL_DIR}/plugins/ranger
+ if [ ! -d "${HCOMPONENT_LIB_DIR}" ]; then
+ echo "INFO: Creating ${HCOMPONENT_LIB_DIR}"
+ mkdir -p ${HCOMPONENT_LIB_DIR}
+ fi
fi
HCOMPONENT_CONF_DIR=${HCOMPONENT_INSTALL_DIR}/conf
@@ -240,6 +246,8 @@ elif [ "${HCOMPONENT_NAME}" = "elasticsearch" ]; then
echo "INFO: Changing ownership of $HCOMPONENT_CONF_DIR to $CFG_OWNER_INF"
chown $CFG_OWNER_INF $HCOMPONENT_CONF_DIR
fi
+elif [ "${HCOMPONENT_NAME}" = "presto" ]; then
+ HCOMPONENT_CONF_DIR=${HCOMPONENT_INSTALL_DIR}/etc
fi
HCOMPONENT_ARCHIVE_CONF_DIR=${HCOMPONENT_CONF_DIR}/.archive
@@ -773,6 +781,29 @@ then
fi
fi
+if [ "${HCOMPONENT_NAME}" = "presto" ]
+then
+ if [ "${action}" = "enable" ]
+ then
+ controlName="ranger"
+ else
+ controlName=""
+ fi
+ dt=`date '+%Y%m%d%H%M%S'`
+ fn=`ls ${HCOMPONENT_CONF_DIR}/access-control.properties 2> /dev/null`
+ if [ -f "${fn}" ]
+ then
+ dn=`dirname ${fn}`
+ bn=`basename ${fn}`
+ bf=${dn}/.${bn}.${dt}
+ echo "backup of ${fn} to ${bf} ..."
+ cp ${fn} ${bf}
+ echo "Add or Update properties file: [${fn}] ... "
+ addOrUpdatePropertyToFile access-control.name $controlName ${fn}
+ fi
+fi
+
+
#
# Set notice to restart the ${HCOMPONENT_NAME}
#
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java
index cbfd649..d82fd70 100755
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java
@@ -48,7 +48,7 @@ public class EmbeddedServiceDefsUtil {
// following servicedef list should be reviewed/updated whenever a new embedded service-def is added
- public static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,nifi-registry,sqoop,kylin,elasticsearch";
+ public static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,nifi-registry,sqoop,kylin,elasticsearch,presto";
private static final String PROPERTY_SUPPORTED_SERVICE_DEFS = "ranger.supportedcomponents";
private Set<String> supportedServiceDefs;
public static final String EMBEDDED_SERVICEDEF_TAG_NAME = "tag";
@@ -69,6 +69,7 @@ public class EmbeddedServiceDefsUtil {
public static final String EMBEDDED_SERVICEDEF_KYLIN_NAME = "kylin";
public static final String EMBEDDED_SERVICEDEF_ABFS_NAME = "abfs";
public static final String EMBEDDED_SERVICEDEF_ELASTICSEARCH_NAME = "elasticsearch";
+ public static final String EMBEDDED_SERVICEDEF_PRESTO_NAME = "presto";
public static final String PROPERTY_CREATE_EMBEDDED_SERVICE_DEFS = "ranger.service.store.create.embedded.service-defs";
@@ -83,6 +84,7 @@ public class EmbeddedServiceDefsUtil {
public static final String SOLR_IMPL_CLASS_NAME = "org.apache.ranger.services.solr.RangerServiceSolr";
public static final String NIFI_IMPL_CLASS_NAME = "org.apache.ranger.services.nifi.RangerServiceNiFi";
public static final String ATLAS_IMPL_CLASS_NAME = "org.apache.ranger.services.atlas.RangerServiceAtlas";
+ public static final String PRESTO_IMPL_CLASS_NAME = "org.apache.ranger.services.presto.RangerServicePresto";
private static EmbeddedServiceDefsUtil instance = new EmbeddedServiceDefsUtil();
@@ -104,6 +106,7 @@ public class EmbeddedServiceDefsUtil {
private RangerServiceDef kylinServiceDef;
private RangerServiceDef abfsServiceDef;
private RangerServiceDef elasticsearchServiceDef;
+ private RangerServiceDef prestoServiceDef;
private RangerServiceDef tagServiceDef;
@@ -148,6 +151,7 @@ public class EmbeddedServiceDefsUtil {
kylinServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_KYLIN_NAME);
abfsServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_ABFS_NAME);
elasticsearchServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_ELASTICSEARCH_NAME);
+ prestoServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_PRESTO_NAME);
// Ensure that tag service def is updated with access types of all service defs
store.updateTagServiceDefForAccessTypes();
@@ -223,6 +227,8 @@ public class EmbeddedServiceDefsUtil {
public long getAbfsServiceDefId() { return getId(abfsServiceDef); }
+ public long getPrestoServiceDefId() { return getId(prestoServiceDef); }
+
public RangerServiceDef getEmbeddedServiceDef(String defType) throws Exception {
RangerServiceDef serviceDef=null;
if(StringUtils.isNotEmpty(defType)){
diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-presto.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-presto.json
new file mode 100644
index 0000000..f0ecf6b
--- /dev/null
+++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-presto.json
@@ -0,0 +1,197 @@
+{
+ "id": 17,
+ "name": "presto",
+ "implClass": "org.apache.ranger.services.presto.RangerServicePresto",
+ "label": "Presto",
+ "description": "Presto",
+ "guid": "379a9fe5-1b6e-4091-a584-4890e245e6c1",
+ "resources": [
+ {
+ "itemId": 1,
+ "name": "catalog",
+ "type": "string",
+ "level": 10,
+ "parent": "",
+ "mandatory": true,
+ "isValidLeaf": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {
+ "wildCard": true,
+ "ignoreCase": true
+ },
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Presto Catalog",
+ "description": "Presto Catalog"
+ },
+ {
+ "itemId": 2,
+ "name": "schema",
+ "type": "string",
+ "level": 20,
+ "parent": "catalog",
+ "mandatory": true,
+ "isValidLeaf": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {
+ "wildCard": true,
+ "ignoreCase": true
+ },
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Presto Schema",
+ "description": "Presto Schema"
+ },
+ {
+ "itemId": 3,
+ "name": "table",
+ "type": "string",
+ "level": 30,
+ "parent": "schema",
+ "mandatory": true,
+ "isValidLeaf": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {
+ "wildCard": true,
+ "ignoreCase": true
+ },
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Presto Table",
+ "description": "Presto Table"
+ },
+ {
+ "itemId": 4,
+ "name": "column",
+ "type": "string",
+ "level": 40,
+ "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": "Presto Column",
+ "description": "Presto Column"
+ }
+ ],
+ "accessTypes": [
+ {
+ "itemId": 1,
+ "name": "select",
+ "label": "Select"
+ },
+ {
+ "itemId": 2,
+ "name": "update",
+ "label": "Update"
+ },
+ {
+ "itemId": 3,
+ "name": "create",
+ "label": "Create"
+ },
+ {
+ "itemId": 4,
+ "name": "drop",
+ "label": "Drop"
+ },
+ {
+ "itemId": 5,
+ "name": "use",
+ "label": "Use"
+ },
+ {
+ "itemId": 6,
+ "name": "alter",
+ "label": "Alter"
+ },
+ {
+ "itemId": 7,
+ "name": "admin",
+ "label": "Admin"
+ },
+ {
+ "itemId": 8,
+ "name": "all",
+ "label": "All",
+ "impliedGrants": [
+ "select",
+ "update",
+ "create",
+ "drop",
+ "use",
+ "alter",
+ "admin"
+ ]
+ }
+ ],
+ "configs": [
+ {
+ "itemId": 1,
+ "name": "username",
+ "type": "string",
+ "mandatory": true,
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Username"
+ },
+ {
+ "itemId": 2,
+ "name": "password",
+ "type": "password",
+ "mandatory": false,
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Password"
+ },
+ {
+ "itemId": 3,
+ "name": "jdbc.driverClassName",
+ "type": "string",
+ "mandatory": true,
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "defaultValue": "io.prestosql.jdbc.PrestoDriver"
+ },
+ {
+ "itemId": 4,
+ "name": "jdbc.url",
+ "type": "string",
+ "mandatory": true,
+ "defaultValue": "",
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": ""
+ }
+ ],
+ "enums": [
+ ],
+ "contextEnrichers": [
+ ],
+ "policyConditions":
+ [
+ ]
+}
\ No newline at end of file
diff --git a/plugin-presto/conf/ranger-policymgr-ssl-changes.cfg b/plugin-presto/conf/ranger-policymgr-ssl-changes.cfg
new file mode 100644
index 0000000..ae347e8
--- /dev/null
+++ b/plugin-presto/conf/ranger-policymgr-ssl-changes.cfg
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SSL Params
+#
+xasecure.policymgr.clientssl.keystore %SSL_KEYSTORE_FILE_PATH% mod create-if-not-exists
+xasecure.policymgr.clientssl.keystore.credential.file jceks://file%CREDENTIAL_PROVIDER_FILE% mod create-if-not-exists
+xasecure.policymgr.clientssl.truststore %SSL_TRUSTSTORE_FILE_PATH% mod create-if-not-exists
+xasecure.policymgr.clientssl.truststore.credential.file jceks://file%CREDENTIAL_PROVIDER_FILE% mod create-if-not-exists
diff --git a/plugin-presto/conf/ranger-policymgr-ssl.xml b/plugin-presto/conf/ranger-policymgr-ssl.xml
new file mode 100644
index 0000000..5ac7cf1
--- /dev/null
+++ b/plugin-presto/conf/ranger-policymgr-ssl.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- The following properties are used for 2-way SSL client server validation -->
+ <property>
+ <name>xasecure.policymgr.clientssl.keystore</name>
+ <value>prestoservice-clientcert.jks</value>
+ <description>
+ Java Keystore files
+ </description>
+ </property>
+ <property>
+ <name>xasecure.policymgr.clientssl.truststore</name>
+ <value>cacerts-xasecure.jks</value>
+ <description>
+ java truststore file
+ </description>
+ </property>
+ <property>
+ <name>xasecure.policymgr.clientssl.keystore.credential.file</name>
+ <value>jceks://file/tmp/keystore-prestoservice-ssl.jceks</value>
+ <description>
+ java keystore credential file
+ </description>
+ </property>
+ <property>
+ <name>xasecure.policymgr.clientssl.truststore.credential.file</name>
+ <value>jceks://file/tmp/truststore-prestoservice-ssl.jceks</value>
+ <description>
+ java truststore credential file
+ </description>
+ </property>
+</configuration>
diff --git a/plugin-presto/conf/ranger-presto-audit-changes.cfg b/plugin-presto/conf/ranger-presto-audit-changes.cfg
new file mode 100644
index 0000000..661b498
--- /dev/null
+++ b/plugin-presto/conf/ranger-presto-audit-changes.cfg
@@ -0,0 +1,58 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#xasecure.audit.db.is.enabled %XAAUDIT.DB.IS_ENABLED% mod create-if-not-exists
+#xasecure.audit.jpa.javax.persistence.jdbc.url %XAAUDIT_DB_JDBC_URL% mod create-if-not-exists
+#xasecure.audit.jpa.javax.persistence.jdbc.user %XAAUDIT.DB.USER_NAME% mod create-if-not-exists
+#xasecure.audit.jpa.javax.persistence.jdbc.password crypted mod create-if-not-exists
+#xasecure.audit.credential.provider.file jceks://file%CREDENTIAL_PROVIDER_FILE% mod create-if-not-exists
+#xasecure.audit.jpa.javax.persistence.jdbc.driver %XAAUDIT_DB_JDBC_DRIVER% mod create-if-not-exists
+
+xasecure.audit.hdfs.is.enabled %XAAUDIT.HDFS.IS_ENABLED% mod create-if-not-exists
+xasecure.audit.hdfs.config.destination.directory %XAAUDIT.HDFS.DESTINATION_DIRECTORY% mod create-if-not-exists
+xasecure.audit.hdfs.config.destination.file %XAAUDIT.HDFS.DESTINTATION_FILE% mod create-if-not-exists
+xasecure.audit.hdfs.config.destination.flush.interval.seconds %XAAUDIT.HDFS.DESTINTATION_FLUSH_INTERVAL_SECONDS% mod create-if-not-exists
+xasecure.audit.hdfs.config.destination.rollover.interval.seconds %XAAUDIT.HDFS.DESTINTATION_ROLLOVER_INTERVAL_SECONDS% mod create-if-not-exists
+xasecure.audit.hdfs.config.destination.open.retry.interval.seconds %XAAUDIT.HDFS.DESTINTATION_OPEN_RETRY_INTERVAL_SECONDS% mod create-if-not-exists
+xasecure.audit.hdfs.config.local.buffer.directory %XAAUDIT.HDFS.LOCAL_BUFFER_DIRECTORY% mod create-if-not-exists
+xasecure.audit.hdfs.config.local.buffer.file %XAAUDIT.HDFS.LOCAL_BUFFER_FILE% mod create-if-not-exists
+xasecure.audit.hdfs.config.local.buffer.flush.interval.seconds %XAAUDIT.HDFS.LOCAL_BUFFER_FLUSH_INTERVAL_SECONDS% mod create-if-not-exists
+xasecure.audit.hdfs.config.local.buffer.rollover.interval.seconds %XAAUDIT.HDFS.LOCAL_BUFFER_ROLLOVER_INTERVAL_SECONDS% mod create-if-not-exists
+xasecure.audit.hdfs.config.local.archive.directory %XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY% mod create-if-not-exists
+xasecure.audit.hdfs.config.local.archive.max.file.count %XAAUDIT.HDFS.LOCAL_ARCHIVE_MAX_FILE_COUNT% mod create-if-not-exists
+
+xasecure.audit.solr.is.enabled %XAAUDIT.SOLR.IS_ENABLED% mod create-if-not-exists
+xasecure.audit.solr.solr_url %XAAUDIT.SOLR.SOLR_URL% mod create-if-not-exists
+
+#V3 configuration
+xasecure.audit.provider.summary.enabled %XAAUDIT.SUMMARY.ENABLE% mod create-if-not-exists
+
+xasecure.audit.destination.solr %XAAUDIT.SOLR.ENABLE% mod create-if-not-exists
+xasecure.audit.destination.solr.urls %XAAUDIT.SOLR.URL% mod create-if-not-exists
+xasecure.audit.destination.solr.user %XAAUDIT.SOLR.USER% mod create-if-not-exists
+xasecure.audit.destination.solr.password %XAAUDIT.SOLR.PASSWORD% mod create-if-not-exists
+xasecure.audit.destination.solr.zookeepers %XAAUDIT.SOLR.ZOOKEEPER% mod create-if-not-exists
+xasecure.audit.destination.solr.batch.filespool.dir %XAAUDIT.SOLR.FILE_SPOOL_DIR% mod create-if-not-exists
+
+xasecure.audit.destination.hdfs %XAAUDIT.HDFS.ENABLE% mod create-if-not-exists
+xasecure.audit.destination.hdfs.batch.filespool.dir %XAAUDIT.HDFS.FILE_SPOOL_DIR% mod create-if-not-exists
+xasecure.audit.destination.hdfs.dir %XAAUDIT.HDFS.HDFS_DIR% mod create-if-not-exists
+
+AZURE.ACCOUNTNAME %XAAUDIT.HDFS.AZURE_ACCOUNTNAME% var
+xasecure.audit.destination.hdfs.config.fs.azure.shellkeyprovider.script %XAAUDIT.HDFS.AZURE_SHELL_KEY_PROVIDER% mod create-if-not-exists
+xasecure.audit.destination.hdfs.config.fs.azure.account.key.%AZURE.ACCOUNTNAME%.blob.core.windows.net %XAAUDIT.HDFS.AZURE_ACCOUNTKEY% mod create-if-not-exists
+xasecure.audit.destination.hdfs.config.fs.azure.account.keyprovider.%AZURE.ACCOUNTNAME%.blob.core.windows.net %XAAUDIT.HDFS.AZURE_ACCOUNTKEY_PROVIDER% mod create-if-not-exists
+
+#xasecure.audit.destination.file %XAAUDIT.FILE.ENABLE% mod create-if-not-exists
+#xasecure.audit.destination.file.dir %XAAUDIT.FILE.DIR% mod create-if-not-exists
diff --git a/plugin-presto/conf/ranger-presto-audit.xml b/plugin-presto/conf/ranger-presto-audit.xml
new file mode 100644
index 0000000..c72771e
--- /dev/null
+++ b/plugin-presto/conf/ranger-presto-audit.xml
@@ -0,0 +1,271 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
+ <property>
+ <name>xasecure.audit.is.enabled</name>
+ <value>true</value>
+ </property>
+
+
+ <!-- DB audit provider configuration -->
+ <property>
+ <name>xasecure.audit.db.is.enabled</name>
+ <value>false</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.db.is.async</name>
+ <value>true</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.db.async.max.queue.size</name>
+ <value>10240</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.db.async.max.flush.interval.ms</name>
+ <value>30000</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.db.batch.size</name>
+ <value>100</value>
+ </property>
+
+ <!-- Properties whose name begin with "xasecure.audit.jpa." are used to configure JPA -->
+ <property>
+ <name>xasecure.audit.jpa.javax.persistence.jdbc.url</name>
+ <value>jdbc:mysql://localhost:3306/ranger_audit</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.jpa.javax.persistence.jdbc.user</name>
+ <value>rangerlogger</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.jpa.javax.persistence.jdbc.password</name>
+ <value>none</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.jpa.javax.persistence.jdbc.driver</name>
+ <value>com.mysql.jdbc.Driver</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.credential.provider.file</name>
+ <value>jceks://file/etc/ranger/prestodev/auditcred.jceks</value>
+ </property>
+
+
+
+ <!-- HDFS audit provider configuration -->
+ <property>
+ <name>xasecure.audit.hdfs.is.enabled</name>
+ <value>false</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.is.async</name>
+ <value>true</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.async.max.queue.size</name>
+ <value>1048576</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.async.max.flush.interval.ms</name>
+ <value>30000</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.encoding</name>
+ <value></value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.destination.directory</name>
+ <value>hdfs://NAMENODE_HOST:8020/ranger/audit/%app-type%/%time:yyyyMMdd%</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.destination.file</name>
+ <value>%hostname%-audit.log</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.destination.flush.interval.seconds</name>
+ <value>900</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.destination.rollover.interval.seconds</name>
+ <value>86400</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.destination.open.retry.interval.seconds</name>
+ <value>60</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.local.buffer.directory</name>
+ <value>/var/log/presto/audit</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.local.buffer.file</name>
+ <value>%time:yyyyMMdd-HHmm.ss%.log</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.local.buffer.file.buffer.size.bytes</name>
+ <value>8192</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.local.buffer.flush.interval.seconds</name>
+ <value>60</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.local.buffer.rollover.interval.seconds</name>
+ <value>600</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.local.archive.directory</name>
+ <value>/var/log/presto/audit/archive</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.hdfs.config.local.archive.max.file.count</name>
+ <value>10</value>
+ </property>
+
+ <!-- Audit to HDFS on Azure Datastore (WASB) requires v3 style settings. Comment the above and uncomment only the
+ following to audit to Azure Blob Datastore via hdfs' WASB schema.
+
+ NOTE: If you specify one audit destination in v3 style then other destinations, if any, must also be specified in v3 style
+ ====
+
+ <property>
+ <name>xasecure.audit.destination.hdfs</name>
+ <value>enabled</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.destination.hdfs.dir</name>
+ <value>wasb://ranger-audit1@youraccount.blob.core.windows.net</value>
+ </property>
+
+ the following 3 correspond to the properties with similar name in core-site.xml, i.e.
+ - fs.azure.account.key.youraccount.blob.core.windows.net => xasecure.audit.destination.hdfs.config.fs.azure.account.key.youraccount.blob.core.windows.net and
+ - fs.azure.account.keyprovider.youraccount.blob.core.windows.net => xasecure.audit.destination.hdfs.config.fs.azure.account.keyprovider.youraccount.blob.core.windows.net,
+ - fs.azure.shellkeyprovider.script => xasecure.audit.destination.hdfs.config.fs.azure.shellkeyprovider.script,
+
+ <property>
+ <name>xasecure.audit.destination.hdfs.config.fs.azure.account.key.youraccount.blob.core.windows.net</name>
+ <value>YOUR ENCRYPTED ACCESS KEY</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.destination.hdfs.config.fs.azure.account.keyprovider.youraccount.blob.core.windows.net</name>
+ <value>org.apache.hadoop.fs.azure.ShellDecryptionKeyProvider</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.destination.hdfs.config.fs.azure.shellkeyprovider.script</name>
+ <value>/usr/lib/python2.7/dist-packages/hdinsight_common/decrypt.sh</value>
+ </property>
+ -->
+
+ <!-- Log4j audit provider configuration -->
+ <property>
+ <name>xasecure.audit.log4j.is.enabled</name>
+ <value>false</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.log4j.is.async</name>
+ <value>false</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.log4j.async.max.queue.size</name>
+ <value>10240</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.log4j.async.max.flush.interval.ms</name>
+ <value>30000</value>
+ </property>
+
+
+ <!-- presto audit provider configuration -->
+ <property>
+ <name>xasecure.audit.presto.is.enabled</name>
+ <value>false</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.presto.async.max.queue.size</name>
+ <value>1</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.presto.async.max.flush.interval.ms</name>
+ <value>1000</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.presto.broker_list</name>
+ <value>localhost:9092</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.presto.topic_name</name>
+ <value>ranger_audits</value>
+ </property>
+
+ <!-- Ranger audit provider configuration -->
+ <property>
+ <name>xasecure.audit.solr.is.enabled</name>
+ <value>false</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.solr.async.max.queue.size</name>
+ <value>1</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.solr.async.max.flush.interval.ms</name>
+ <value>1000</value>
+ </property>
+
+ <property>
+ <name>xasecure.audit.solr.solr_url</name>
+ <value>http://localhost:6083/solr/ranger_audits</value>
+ </property>
+</configuration>
diff --git a/plugin-presto/conf/ranger-presto-security-changes.cfg b/plugin-presto/conf/ranger-presto-security-changes.cfg
new file mode 100644
index 0000000..15fc7fd
--- /dev/null
+++ b/plugin-presto/conf/ranger-presto-security-changes.cfg
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Change the original policy parameter to work with policy manager based.
+#
+#
+ranger.plugin.presto.service.name %REPOSITORY_NAME% mod create-if-not-exists
+
+ranger.plugin.presto.policy.source.impl org.apache.ranger.admin.client.RangerAdminRESTClient mod create-if-not-exists
+
+ranger.plugin.presto.policy.rest.url %POLICY_MGR_URL% mod create-if-not-exists
+ranger.plugin.presto.policy.rest.ssl.config.file /etc/hadoop/conf/ranger-policymgr-ssl.xml mod create-if-not-exists
+ranger.plugin.presto.policy.pollIntervalMs 30000 mod create-if-not-exists
+ranger.plugin.presto.policy.cache.dir %POLICY_CACHE_FILE_PATH% mod create-if-not-exists
+ranger.plugin.presto.policy.rest.client.connection.timeoutMs 120000 mod create-if-not-exists
+ranger.plugin.presto.policy.rest.client.read.timeoutMs 30000 mod create-if-not-exists
\ No newline at end of file
diff --git a/plugin-presto/conf/ranger-presto-security.xml b/plugin-presto/conf/ranger-presto-security.xml
new file mode 100644
index 0000000..9feae81
--- /dev/null
+++ b/plugin-presto/conf/ranger-presto-security.xml
@@ -0,0 +1,74 @@
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration>
+ <property>
+ <name>ranger.plugin.presto.service.name</name>
+ <value>prestoservice</value>
+ <description>
+ Name of the Ranger service containing policies for this Presto instance
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.presto.policy.source.impl</name>
+ <value>org.apache.ranger.admin.client.RangerAdminRESTClient</value>
+ <description>
+ Class to retrieve policies from the source
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.presto.policy.rest.url</name>
+ <value>http://localhost:6080</value>
+ <description>
+ URL to Ranger Admin
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.presto.policy.rest.ssl.config.file</name>
+ <value>/etc/hadoop/conf/ranger-policymgr-ssl.xml</value>
+ <description>
+ Path to the file containing SSL details to contact Ranger Admin
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.presto.policy.pollIntervalMs</name>
+ <value>30000</value>
+ <description>
+ How often to poll for changes in policies?
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.presto.policy.rest.client.connection.timeoutMs</name>
+ <value>30000</value>
+ <description>
+ S3 Plugin RangerRestClient Connection Timeout in Milli Seconds
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.presto.policy.rest.client.read.timeoutMs</name>
+ <value>30000</value>
+ <description>
+ S3 Plugin RangerRestClient read Timeout in Milli Seconds
+ </description>
+ </property>
+</configuration>
diff --git a/plugin-presto/pom.xml b/plugin-presto/pom.xml
new file mode 100644
index 0000000..f066d31
--- /dev/null
+++ b/plugin-presto/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>ranger-presto-plugin</artifactId>
+ <name>Presto Security Plugin</name>
+ <description>Presto Security Plugin</description>
+ <packaging>jar</packaging>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <parent>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>io.prestosql</groupId>
+ <artifactId>presto-spi</artifactId>
+ <version>${presto.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.prestosql</groupId>
+ <artifactId>presto-jdbc</artifactId>
+ <version>${presto.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-audit</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/plugin-presto/scripts/install.properties b/plugin-presto/scripts/install.properties
new file mode 100644
index 0000000..3110e2d
--- /dev/null
+++ b/plugin-presto/scripts/install.properties
@@ -0,0 +1,140 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Location of Policy Manager URL
+#
+# Example:
+# POLICY_MGR_URL=http://policymanager.xasecure.net:6080
+#
+POLICY_MGR_URL=
+
+#
+# This is the repository name created within policy manager
+#
+# Example:
+# REPOSITORY_NAME=prestodev
+#
+REPOSITORY_NAME=
+
+#
+# Name of the directory where the component's lib and conf directory exist.
+# This location should be relative to the parent of the directory containing
+# the plugin installation files.
+#
+COMPONENT_INSTALL_DIR_NAME=../presto
+
+# Enable audit logs to Solr
+#Example
+#XAAUDIT.SOLR.ENABLE=true
+#XAAUDIT.SOLR.URL=http://localhost:6083/solr/ranger_audits
+#XAAUDIT.SOLR.ZOOKEEPER=
+#XAAUDIT.SOLR.FILE_SPOOL_DIR=/var/log/presto/audit/solr/spool
+
+XAAUDIT.SOLR.ENABLE=false
+XAAUDIT.SOLR.URL=NONE
+XAAUDIT.SOLR.USER=NONE
+XAAUDIT.SOLR.PASSWORD=NONE
+XAAUDIT.SOLR.ZOOKEEPER=NONE
+XAAUDIT.SOLR.FILE_SPOOL_DIR=/var/log/presto/audit/solr/spool
+
+# Enable audit logs to HDFS
+#Example
+#XAAUDIT.HDFS.ENABLE=true
+#XAAUDIT.HDFS.HDFS_DIR=hdfs://node-1.example.com:8020/ranger/audit
+# If using Azure Blob Storage
+#XAAUDIT.HDFS.HDFS_DIR=wasb[s]://<containername>@<accountname>.blob.core.windows.net/<path>
+#XAAUDIT.HDFS.HDFS_DIR=wasb://ranger_audit_container@my-azure-account.blob.core.windows.net/ranger/audit
+#XAAUDIT.HDFS.FILE_SPOOL_DIR=/var/log/presto/audit/hdfs/spool
+
+XAAUDIT.HDFS.ENABLE=false
+XAAUDIT.HDFS.HDFS_DIR=hdfs://__REPLACE__NAME_NODE_HOST:8020/ranger/audit
+XAAUDIT.HDFS.FILE_SPOOL_DIR=/var/log/presto/audit/hdfs/spool
+
+# Following additional propertis are needed When auditing to Azure Blob Storage via HDFS
+# Get these values from your /etc/hadoop/conf/core-site.xml
+#XAAUDIT.HDFS.HDFS_DIR=wasb[s]://<containername>@<accountname>.blob.core.windows.net/<path>
+XAAUDIT.HDFS.AZURE_ACCOUNTNAME=__REPLACE_AZURE_ACCOUNT_NAME
+XAAUDIT.HDFS.AZURE_ACCOUNTKEY=__REPLACE_AZURE_ACCOUNT_KEY
+XAAUDIT.HDFS.AZURE_SHELL_KEY_PROVIDER=__REPLACE_AZURE_SHELL_KEY_PROVIDER
+XAAUDIT.HDFS.AZURE_ACCOUNTKEY_PROVIDER=__REPLACE_AZURE_ACCOUNT_KEY_PROVIDER
+
+# End of V3 properties
+
+
+#
+# Audit to HDFS Configuration
+#
+# If XAAUDIT.HDFS.IS_ENABLED is set to true, please replace tokens
+# that start with __REPLACE__ with appropriate values
+# XAAUDIT.HDFS.IS_ENABLED=true
+# XAAUDIT.HDFS.DESTINATION_DIRECTORY=hdfs://__REPLACE__NAME_NODE_HOST:8020/ranger/audit/%app-type%/%time:yyyyMMdd%
+# XAAUDIT.HDFS.LOCAL_BUFFER_DIRECTORY=__REPLACE__LOG_DIR/presto/audit
+# XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=__REPLACE__LOG_DIR/presto/audit/archive
+#
+# Example:
+# XAAUDIT.HDFS.IS_ENABLED=true
+# XAAUDIT.HDFS.DESTINATION_DIRECTORY=hdfs://namenode.example.com:8020/ranger/audit/%app-type%/%time:yyyyMMdd%
+# XAAUDIT.HDFS.LOCAL_BUFFER_DIRECTORY=/var/log/presto/audit
+# XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=/var/log/presto/audit/archive
+#
+XAAUDIT.HDFS.IS_ENABLED=false
+XAAUDIT.HDFS.DESTINATION_DIRECTORY=hdfs://__REPLACE__NAME_NODE_HOST:8020/ranger/audit/%app-type%/%time:yyyyMMdd%
+XAAUDIT.HDFS.LOCAL_BUFFER_DIRECTORY=__REPLACE__LOG_DIR/presto/audit
+XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=__REPLACE__LOG_DIR/presto/audit/archive
+
+XAAUDIT.HDFS.DESTINTATION_FILE=%hostname%-audit.log
+XAAUDIT.HDFS.DESTINTATION_FLUSH_INTERVAL_SECONDS=900
+XAAUDIT.HDFS.DESTINTATION_ROLLOVER_INTERVAL_SECONDS=86400
+XAAUDIT.HDFS.DESTINTATION_OPEN_RETRY_INTERVAL_SECONDS=60
+XAAUDIT.HDFS.LOCAL_BUFFER_FILE=%time:yyyyMMdd-HHmm.ss%.log
+XAAUDIT.HDFS.LOCAL_BUFFER_FLUSH_INTERVAL_SECONDS=60
+XAAUDIT.HDFS.LOCAL_BUFFER_ROLLOVER_INTERVAL_SECONDS=600
+XAAUDIT.HDFS.LOCAL_ARCHIVE_MAX_FILE_COUNT=10
+
+#Solr Audit Provder
+XAAUDIT.SOLR.IS_ENABLED=false
+XAAUDIT.SOLR.MAX_QUEUE_SIZE=1
+XAAUDIT.SOLR.MAX_FLUSH_INTERVAL_MS=1000
+XAAUDIT.SOLR.SOLR_URL=http://localhost:6083/solr/ranger_audits
+
+#
+# SSL Client Certificate Information
+#
+# Example:
+# SSL_KEYSTORE_FILE_PATH=/etc/hadoop/conf/ranger-plugin-keystore.jks
+# SSL_KEYSTORE_PASSWORD=none
+# SSL_TRUSTSTORE_FILE_PATH=/etc/hadoop/conf/ranger-plugin-truststore.jks
+# SSL_TRUSTSTORE_PASSWORD=none
+#
+# You do not need use SSL between agent and security admin tool, please leave these sample value as it is.
+#
+SSL_KEYSTORE_FILE_PATH=/etc/hadoop/conf/ranger-plugin-keystore.jks
+SSL_KEYSTORE_PASSWORD=myKeyFilePassword
+SSL_TRUSTSTORE_FILE_PATH=/etc/hadoop/conf/ranger-plugin-truststore.jks
+SSL_TRUSTSTORE_PASSWORD=changeit
+
+#
+# Custom component user
+# CUSTOM_COMPONENT_USER=<custom-user>
+# keep blank if component user is default
+CUSTOM_USER=presto
+
+
+#
+# Custom component group
+# CUSTOM_COMPONENT_GROUP=<custom-group>
+# keep blank if component group is default
+CUSTOM_GROUP=hadoop
diff --git a/plugin-presto/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControl.java b/plugin-presto/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControl.java
new file mode 100644
index 0000000..3ab63f5
--- /dev/null
+++ b/plugin-presto/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControl.java
@@ -0,0 +1,459 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.presto.authorizer;
+
+import io.prestosql.spi.connector.CatalogSchemaName;
+import io.prestosql.spi.connector.CatalogSchemaTableName;
+import io.prestosql.spi.connector.SchemaTableName;
+import io.prestosql.spi.security.AccessDeniedException;
+import io.prestosql.spi.security.Identity;
+import io.prestosql.spi.security.PrestoPrincipal;
+import io.prestosql.spi.security.Privilege;
+import io.prestosql.spi.security.SystemAccessControl;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler;
+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.RangerPolicyEngine;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static java.util.Locale.ENGLISH;
+
+public class RangerSystemAccessControl
+ implements SystemAccessControl {
+
+ public static String RANGER_CONFIG_KEYTAB = "ranger.keytab";
+ public static String RANGER_CONFIG_PRINCIPAL = "ranger.principal";
+
+ public static String RANGER_PRESTO_SERVICETYPE = "presto";
+ public static String RANGER_PRESTO_APPID = "presto";
+
+ private static Logger LOG = LoggerFactory.getLogger(RangerSystemAccessControl.class);
+
+ private RangerBasePlugin rangerPlugin;
+
+ public RangerSystemAccessControl(Map<String, String> config) {
+ super();
+
+ if (config.get(RANGER_CONFIG_KEYTAB) != null && config.get(RANGER_CONFIG_PRINCIPAL) != null) {
+ String keytab = config.get(RANGER_CONFIG_KEYTAB);
+ String principal = config.get(RANGER_CONFIG_PRINCIPAL);
+
+ LOG.info("Performing kerberos login with principal " + principal + " and keytab " + keytab);
+
+ try {
+ UserGroupInformation.setConfiguration(new Configuration());
+ UserGroupInformation.loginUserFromKeytab(principal, keytab);
+ } catch (IOException ioe) {
+ LOG.error("Kerberos login failed", ioe);
+ throw new RuntimeException(ioe);
+ }
+ }
+ rangerPlugin = new RangerBasePlugin(RANGER_PRESTO_SERVICETYPE, RANGER_PRESTO_APPID);
+ rangerPlugin.init();
+ rangerPlugin.setResultProcessor(new RangerDefaultAuditHandler());
+ }
+
+ private boolean checkPermission(RangerPrestoResource resource, Identity identity, PrestoAccessType accessType) {
+ boolean ret = false;
+
+ UserGroupInformation ugi = UserGroupInformation.createRemoteUser(identity.getUser());
+
+ String[] groups = ugi != null ? ugi.getGroupNames() : null;
+
+ Set<String> userGroups = null;
+ if (groups != null && groups.length > 0) {
+ userGroups = new HashSet<>(Arrays.asList(groups));
+ }
+
+ RangerPrestoAccessRequest request = new RangerPrestoAccessRequest(
+ resource,
+ identity.getUser(),
+ userGroups,
+ accessType
+ );
+
+ RangerAccessResult result = rangerPlugin.isAccessAllowed(request);
+ if (result != null && result.getIsAllowed()) {
+ ret = true;
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void checkCanSetUser(Optional<Principal> principal, String userName) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerSystemAccessControl.checkCanSetUser(" + userName + ")");
+ }
+
+ /*
+ if (!principal.isPresent()) {
+ //AccessDeniedException.denySetUser(principal, userName);
+ }*/
+
+ //AccessDeniedException.denySetUser(principal, userName);
+ }
+
+ @Override
+ public void checkCanSetSystemSessionProperty(Identity identity, String propertyName) {
+ if (!checkPermission(new RangerPrestoResource(), identity, PrestoAccessType.ADMIN)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanSetSystemSessionProperty denied");
+ AccessDeniedException.denySetSystemSessionProperty(propertyName);
+ }
+ }
+
+ @Override
+ public void checkCanAccessCatalog(Identity identity, String catalogName) {
+ if (!checkPermission(createResource(catalogName), identity, PrestoAccessType.SELECT)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanAccessCatalog(" + catalogName + ") denied");
+ AccessDeniedException.denyCatalogAccess(catalogName);
+ }
+ }
+
+ @Override
+ public Set<String> filterCatalogs(Identity identity, Set<String> catalogs) {
+ return catalogs;
+ }
+
+ @Override
+ public void checkCanCreateSchema(Identity identity, CatalogSchemaName schema) {
+ if (!checkPermission(createResource(schema.getCatalogName(), schema.getSchemaName()), identity, PrestoAccessType.CREATE)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanCreateSchema(" + schema.getSchemaName() + ") denied");
+ AccessDeniedException.denyCreateSchema(schema.getSchemaName());
+ }
+ }
+
+ @Override
+ public void checkCanDropSchema(Identity identity, CatalogSchemaName schema) {
+ if (!checkPermission(createResource(schema.getCatalogName(), schema.getSchemaName()), identity, PrestoAccessType.DROP)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanDropSchema(" + schema.getSchemaName() + ") denied");
+ AccessDeniedException.denyDropSchema(schema.getSchemaName());
+ }
+ }
+
+ @Override
+ public void checkCanRenameSchema(Identity identity, CatalogSchemaName schema, String newSchemaName) {
+ RangerPrestoResource res = createResource(schema.getCatalogName(), schema.getSchemaName());
+ if (!checkPermission(res, identity, PrestoAccessType.ALTER)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanRenameSchema(" + schema.getSchemaName() + ") denied");
+ AccessDeniedException.denyRenameSchema(schema.getSchemaName(), newSchemaName);
+ }
+ }
+
+ @Override
+ public void checkCanShowSchemas(Identity identity, String catalogName) {
+ if (!checkPermission(createResource(catalogName), identity, PrestoAccessType.SELECT)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanShowSchemas(" + catalogName + ") denied");
+ AccessDeniedException.denyShowSchemas(catalogName);
+ }
+ }
+
+ @Override
+ public Set<String> filterSchemas(Identity identity, String catalogName, Set<String> schemaNames) {
+ LOG.debug("==> RangerSystemAccessControl.filterSchemas(" + catalogName + ")");
+ return schemaNames;
+ }
+
+ @Override
+ public void checkCanCreateTable(Identity identity, CatalogSchemaTableName table) {
+ if (!checkPermission(createResource(table), identity, PrestoAccessType.CREATE)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanCreateTable(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyCreateTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDropTable(Identity identity, CatalogSchemaTableName table) {
+ if (!checkPermission(createResource(table), identity, PrestoAccessType.DROP)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanDropTable(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyDropTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanRenameTable(Identity identity, CatalogSchemaTableName table, CatalogSchemaTableName newTable) {
+ RangerPrestoResource res = createResource(table);
+ if (!checkPermission(res, identity, PrestoAccessType.ALTER)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanRenameTable(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyRenameTable(table.getSchemaTableName().getTableName(), newTable.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanShowTablesMetadata(Identity identity, CatalogSchemaName schema) {
+ if (!checkPermission(createResource(schema.getCatalogName(), schema.getSchemaName()), identity, PrestoAccessType.SELECT)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanShowTablesMetadata(" + schema.getSchemaName() + ") denied");
+ AccessDeniedException.denyShowTablesMetadata(schema.getSchemaName());
+ }
+ }
+
+ @Override
+ public Set<SchemaTableName> filterTables(Identity identity, String catalogName, Set<SchemaTableName> tableNames) {
+ LOG.debug("==> RangerSystemAccessControl.filterTables(" + catalogName + ")");
+ return tableNames;
+ }
+
+ @Override
+ public void checkCanAddColumn(Identity identity, CatalogSchemaTableName table) {
+ RangerPrestoResource res = createResource(table);
+ if (!checkPermission(res, identity, PrestoAccessType.ALTER)) {
+ AccessDeniedException.denyAddColumn(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDropColumn(Identity identity, CatalogSchemaTableName table) {
+ RangerPrestoResource res = createResource(table);
+ if (!checkPermission(res, identity, PrestoAccessType.ALTER)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanDropColumn(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyDropColumn(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanRenameColumn(Identity identity, CatalogSchemaTableName table) {
+ RangerPrestoResource res = createResource(table);
+ if (!checkPermission(res, identity, PrestoAccessType.ALTER)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanRenameColumn(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyRenameColumn(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanSelectFromColumns(Identity identity, CatalogSchemaTableName table, Set<String> columns) {
+ for (RangerPrestoResource res : createResource(table, columns)) {
+ if (!checkPermission(res, identity, PrestoAccessType.SELECT)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanSelectFromColumns(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denySelectColumns(table.getSchemaTableName().getTableName(), columns);
+ }
+ }
+ }
+
+ @Override
+ public void checkCanInsertIntoTable(Identity identity, CatalogSchemaTableName table) {
+ RangerPrestoResource res = createResource(table);
+ if (!checkPermission(res, identity, PrestoAccessType.INSERT)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanInsertIntoTable(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyInsertTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDeleteFromTable(Identity identity, CatalogSchemaTableName table) {
+ if (!checkPermission(createResource(table), identity, PrestoAccessType.DELETE)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanDeleteFromTable(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyDeleteTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanCreateView(Identity identity, CatalogSchemaTableName view) {
+ if (!checkPermission(createResource(view), identity, PrestoAccessType.CREATE)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanCreateView(" + view.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyCreateView(view.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDropView(Identity identity, CatalogSchemaTableName view) {
+ if (!checkPermission(createResource(view), identity, PrestoAccessType.DROP)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanDropView(" + view.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyCreateView(view.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanCreateViewWithSelectFromColumns(Identity identity, CatalogSchemaTableName table, Set<String> columns) {
+ for (RangerPrestoResource res : createResource(table, columns)) {
+ if (!checkPermission(res, identity, PrestoAccessType.CREATE)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanDropView(" + table.getSchemaTableName().getTableName() + ") denied");
+ AccessDeniedException.denyCreateViewWithSelect(table.getSchemaTableName().getTableName(), identity);
+ }
+ }
+ }
+
+ @Override
+ public void checkCanSetCatalogSessionProperty(Identity identity, String catalogName, String propertyName) {
+ if (!checkPermission(createResource(catalogName), identity, PrestoAccessType.ADMIN)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanSetSystemSessionProperty(" + catalogName + ") denied");
+ AccessDeniedException.denySetCatalogSessionProperty(catalogName, propertyName);
+ }
+ }
+
+ @Override
+ public void checkCanGrantTablePrivilege(Identity identity, Privilege privilege, CatalogSchemaTableName table, PrestoPrincipal grantee, boolean withGrantOption) {
+ if (!checkPermission(createResource(table), identity, PrestoAccessType.ADMIN)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanGrantTablePrivilege(" + table + ") denied");
+ AccessDeniedException.denyGrantTablePrivilege(privilege.toString(), table.toString());
+ }
+ }
+
+ @Override
+ public void checkCanRevokeTablePrivilege(Identity identity, Privilege privilege, CatalogSchemaTableName table, PrestoPrincipal revokee, boolean grantOptionFor) {
+ if (!checkPermission(createResource(table), identity, PrestoAccessType.ADMIN)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanRevokeTablePrivilege(" + table + ") denied");
+ AccessDeniedException.denyRevokeTablePrivilege(privilege.toString(), table.toString());
+ }
+ }
+
+ @Override
+ public void checkCanShowRoles(Identity identity, String catalogName) {
+ if (!checkPermission(createResource(catalogName), identity, PrestoAccessType.ADMIN)) {
+ LOG.info("==> RangerSystemAccessControl.checkCanShowRoles(" + catalogName + ") denied");
+ AccessDeniedException.denyShowRoles(catalogName);
+ }
+ }
+
+ private static RangerPrestoResource createResource(CatalogSchemaName catalogSchemaName) {
+ return createResource(catalogSchemaName.getCatalogName(), catalogSchemaName.getSchemaName());
+ }
+
+ private static RangerPrestoResource createResource(CatalogSchemaTableName catalogSchemaTableName) {
+ return createResource(catalogSchemaTableName.getCatalogName(),
+ catalogSchemaTableName.getSchemaTableName().getSchemaName(),
+ catalogSchemaTableName.getSchemaTableName().getTableName());
+ }
+
+ private static RangerPrestoResource createResource(String catalogName) {
+ return new RangerPrestoResource(catalogName, Optional.empty(), Optional.empty());
+ }
+
+ private static RangerPrestoResource createResource(String catalogName, String schemaName) {
+ return new RangerPrestoResource(catalogName, Optional.of(schemaName), Optional.empty());
+ }
+
+ private static RangerPrestoResource createResource(String catalogName, String schemaName, final String tableName) {
+ return new RangerPrestoResource(catalogName, Optional.of(schemaName), Optional.of(tableName));
+ }
+
+ private static RangerPrestoResource createResource(String catalogName, String schemaName, final String tableName, final Optional<String> column) {
+ return new RangerPrestoResource(catalogName, Optional.of(schemaName), Optional.of(tableName), column);
+ }
+
+ private static List<RangerPrestoResource> createResource(CatalogSchemaTableName table, Set<String> columns) {
+ List<RangerPrestoResource> colRequests = new ArrayList<>();
+
+ if (columns.size() > 0) {
+ for (String column : columns) {
+ RangerPrestoResource rangerPrestoResource = createResource(table.getCatalogName(),
+ table.getSchemaTableName().getSchemaName(),
+ table.getSchemaTableName().getTableName(), Optional.of(column));
+ colRequests.add(rangerPrestoResource);
+ }
+ } else {
+ colRequests.add(createResource(table.getCatalogName(),
+ table.getSchemaTableName().getSchemaName(),
+ table.getSchemaTableName().getTableName(), Optional.empty()));
+ }
+ return colRequests;
+ }
+}
+
+class RangerPrestoResource
+ extends RangerAccessResourceImpl {
+
+
+ public static final String KEY_CATALOG = "catalog";
+ public static final String KEY_SCHEMA = "schema";
+ public static final String KEY_TABLE = "table";
+ public static final String KEY_COLUMN = "column";
+
+ public RangerPrestoResource() {}
+
+ public RangerPrestoResource(String catalogName, Optional<String> schema, Optional<String> table) {
+ setValue(KEY_CATALOG, catalogName);
+ if (schema.isPresent()) {
+ setValue(KEY_SCHEMA, schema.get());
+ }
+ if (table.isPresent()) {
+ setValue(KEY_TABLE, table.get());
+ }
+ }
+
+ public RangerPrestoResource(String catalogName, Optional<String> schema, Optional<String> table, Optional<String> column) {
+ setValue(KEY_CATALOG, catalogName);
+ if (schema.isPresent()) {
+ setValue(KEY_SCHEMA, schema.get());
+ }
+ if (table.isPresent()) {
+ setValue(KEY_TABLE, table.get());
+ }
+ if (column.isPresent()) {
+ setValue(KEY_COLUMN, column.get());
+ }
+ }
+
+ public String getCatalogName() {
+ return (String) getValue(KEY_CATALOG);
+ }
+
+ public String getTable() {
+ return (String) getValue(KEY_TABLE);
+ }
+
+ public String getCatalog() {
+ return (String) getValue(KEY_CATALOG);
+ }
+
+ public String getSchema() { return (String) getValue(KEY_SCHEMA); }
+
+ public Optional<SchemaTableName> getSchemaTable() {
+ final String schema = getSchema();
+ if (StringUtils.isNotEmpty(schema)) {
+ return Optional.of(new SchemaTableName(schema, Optional.ofNullable(getTable()).orElse("*")));
+ }
+ return Optional.empty();
+ }
+}
+
+class RangerPrestoAccessRequest
+ extends RangerAccessRequestImpl {
+ public RangerPrestoAccessRequest(RangerPrestoResource resource,
+ String user,
+ Set<String> userGroups,
+ PrestoAccessType prestoAccessType)
+
+ {
+ super(resource,
+ prestoAccessType == PrestoAccessType.USE ? RangerPolicyEngine.ANY_ACCESS :
+ prestoAccessType == PrestoAccessType.ADMIN ? RangerPolicyEngine.ADMIN_ACCESS :
+ prestoAccessType.name().toLowerCase(ENGLISH), user,
+ userGroups);
+ }
+}
+
+enum PrestoAccessType {
+ CREATE, DROP, SELECT, INSERT, DELETE, USE, ALTER, ALL, ADMIN;
+}
\ No newline at end of file
diff --git a/plugin-presto/src/main/java/org/apache/ranger/services/presto/RangerServicePresto.java b/plugin-presto/src/main/java/org/apache/ranger/services/presto/RangerServicePresto.java
new file mode 100644
index 0000000..f41b2c8
--- /dev/null
+++ b/plugin-presto/src/main/java/org/apache/ranger/services/presto/RangerServicePresto.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.presto;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.client.HadoopException;
+import org.apache.ranger.plugin.service.RangerBaseService;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.apache.ranger.services.presto.client.PrestoResourceManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RangerServicePresto extends RangerBaseService {
+ private static final Log LOG = LogFactory.getLog(RangerServicePresto.class);
+
+ @Override
+ public Map<String, Object> validateConfig() throws Exception {
+ Map<String, Object> ret = new HashMap<String, Object>();
+ String serviceName = getServiceName();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("RangerServicePresto.validateConfig(): Service: " +
+ serviceName);
+ }
+
+ if (configs != null) {
+ try {
+ ret = PrestoResourceManager.connectionTest(serviceName, configs);
+ } catch (HadoopException he) {
+ LOG.error("<== RangerServicePresto.validateConfig Error:" + he);
+ throw he;
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("RangerServicePresto.validateConfig(): Response: " +
+ ret);
+ }
+ return ret;
+ }
+
+ @Override
+ public List<String> lookupResource(ResourceLookupContext context) throws Exception {
+
+ List<String> ret = new ArrayList<String>();
+ String serviceName = getServiceName();
+ String serviceType = getServiceType();
+ Map<String,String> configs = getConfigs();
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerServiceHive.lookupResource Context: (" + context + ")");
+ }
+ if (context != null) {
+ try {
+ ret = PrestoResourceManager.getPrestoResources(serviceName, serviceType, configs,context);
+ } catch (Exception e) {
+ LOG.error( "<==RangerServicePresto.lookupResource Error : " + e);
+ throw e;
+ }
+ }
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerServicePresto.lookupResource Response: (" + ret + ")");
+ }
+ return ret;
+ }
+
+}
diff --git a/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoClient.java b/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoClient.java
new file mode 100644
index 0000000..37c2346
--- /dev/null
+++ b/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoClient.java
@@ -0,0 +1,556 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.presto.client;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.client.BaseClient;
+import org.apache.ranger.plugin.client.HadoopConfigHolder;
+import org.apache.ranger.plugin.client.HadoopException;
+
+import javax.security.auth.Subject;
+import java.io.Closeable;
+import java.security.PrivilegedAction;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLTimeoutException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class PrestoClient extends BaseClient implements Closeable {
+ public static final String PRESTO_USER_NAME_PROP = "user";
+ public static final String PRESTO_PASSWORD_PROP = "password";
+
+ private static final Log LOG = LogFactory.getLog(PrestoClient.class);
+
+ private static final String ERR_MSG = "You can still save the repository and start creating "
+ + "policies, but you would not be able to use autocomplete for "
+ + "resource names. Check ranger_admin.log for more info.";
+
+ private Connection con;
+
+ public PrestoClient(String serviceName) throws Exception {
+ super(serviceName, null);
+ init();
+ }
+
+ public PrestoClient(String serviceName, Map<String, String> properties) throws Exception {
+ super(serviceName, properties);
+ init();
+ }
+
+ private void init() throws Exception {
+ Subject.doAs(getLoginSubject(), new PrivilegedAction<Void>() {
+ public Void run() {
+ initConnection();
+ return null;
+ }
+ });
+ }
+
+ private void initConnection() {
+ Properties prop = getConfigHolder().getRangerSection();
+ String driverClassName = prop.getProperty("jdbc.driverClassName");
+ String url = prop.getProperty("jdbc.url");
+
+ Properties prestoProperties = new Properties();
+ prestoProperties.put(PRESTO_USER_NAME_PROP, prop.getProperty(HadoopConfigHolder.RANGER_LOGIN_USER_NAME_PROP));
+ prestoProperties.put(PRESTO_PASSWORD_PROP, prop.getProperty(HadoopConfigHolder.RANGER_LOGIN_PASSWORD));
+
+ if (driverClassName != null) {
+ try {
+ Driver driver = (Driver) Class.forName(driverClassName).newInstance();
+ DriverManager.registerDriver(driver);
+ } catch (SQLException e) {
+ String msgDesc = "initConnection: Caught SQLException while registering"
+ + " the Presto driver.";
+ HadoopException hdpException = new HadoopException(msgDesc, e);
+ hdpException.generateResponseDataMap(false, getMessage(e),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ } catch (IllegalAccessException ilae) {
+ String msgDesc = "initConnection: Class or its nullary constructor might not accessible.";
+ HadoopException hdpException = new HadoopException(msgDesc, ilae);
+ hdpException.generateResponseDataMap(false, getMessage(ilae),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ } catch (InstantiationException ie) {
+ String msgDesc = "initConnection: Class may not have its nullary constructor or "
+ + "may be the instantiation fails for some other reason.";
+ HadoopException hdpException = new HadoopException(msgDesc, ie);
+ hdpException.generateResponseDataMap(false, getMessage(ie),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ } catch (ExceptionInInitializerError eie) {
+ String msgDesc = "initConnection: Got ExceptionInInitializerError, "
+ + "The initialization provoked by this method fails.";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ eie);
+ hdpException.generateResponseDataMap(false, getMessage(eie),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ } catch (SecurityException se) {
+ String msgDesc = "initConnection: unable to initiate connection to Presto instance,"
+ + " The caller's class loader is not the same as or an ancestor "
+ + "of the class loader for the current class and invocation of "
+ + "s.checkPackageAccess() denies access to the package of this class.";
+ HadoopException hdpException = new HadoopException(msgDesc, se);
+ hdpException.generateResponseDataMap(false, getMessage(se),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ } catch (Throwable t) {
+ String msgDesc = "initConnection: Unable to connect to Presto instance, "
+ + "please provide valid value of field : {jdbc.driverClassName}.";
+ HadoopException hdpException = new HadoopException(msgDesc, t);
+ hdpException.generateResponseDataMap(false, getMessage(t),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ }
+ }
+
+ try {
+ con = DriverManager.getConnection(url, prestoProperties);
+ } catch (SQLException e) {
+ String msgDesc = "Unable to connect to Presto instance.";
+ HadoopException hdpException = new HadoopException(msgDesc, e);
+ hdpException.generateResponseDataMap(false, getMessage(e),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ } catch (SecurityException se) {
+ String msgDesc = "Unable to connect to Presto instance.";
+ HadoopException hdpException = new HadoopException(msgDesc, se);
+ hdpException.generateResponseDataMap(false, getMessage(se),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ } catch (Throwable t) {
+ String msgDesc = "initConnection: Unable to connect to Presto instance, ";
+ HadoopException hdpException = new HadoopException(msgDesc, t);
+ hdpException.generateResponseDataMap(false, getMessage(t),
+ msgDesc + ERR_MSG, null, null);
+ throw hdpException;
+ }
+
+ }
+
+ private List<String> getCatalogs(String needle, List<String> catalogs) throws HadoopException {
+ List<String> ret = new ArrayList<>();
+ if (con != null) {
+ Statement stat = null;
+ ResultSet rs = null;
+ String sql = "SHOW CATALOGS";
+
+ try {
+ if (needle != null && !needle.isEmpty() && !needle.equals("*")) {
+ // Cannot use a prepared statement for this as presto does not support that
+ sql += " LIKE '" + StringEscapeUtils.escapeSql(needle) + "%'";
+ }
+ stat = con.createStatement();
+ rs = stat.executeQuery(sql);
+ while (rs.next()) {
+ String catalogName = rs.getString(1);
+ if (catalogs != null && catalogs.contains(catalogName)) {
+ continue;
+ }
+ ret.add(catalogName);
+ }
+ } catch (SQLTimeoutException sqlt) {
+ String msgDesc = "Time Out, Unable to execute SQL [" + sql
+ + "].";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ sqlt);
+ hdpException.generateResponseDataMap(false, getMessage(sqlt),
+ msgDesc + ERR_MSG, null, null);
+ } catch (SQLException se) {
+ String msg = "Unable to execute SQL [" + sql + "]. ";
+ HadoopException he = new HadoopException(msg, se);
+ he.generateResponseDataMap(false, getMessage(se), msg + ERR_MSG,
+ null, null);
+ throw he;
+ } finally {
+ close(rs);
+ close(stat);
+ }
+ }
+ return ret;
+ }
+
+ public List<String> getCatalogList(String needle, final List<String> catalogs) throws HadoopException {
+ final String ndl = needle;
+ final List<String> catList = catalogs;
+
+ List<String> dbs = Subject.doAs(getLoginSubject(), new PrivilegedAction<List<String>>() {
+ @Override
+ public List<String> run() {
+ List<String> ret = null;
+ try {
+ ret = getCatalogs(ndl, catList);
+ } catch (HadoopException he) {
+ LOG.error("<== PrestoClient getCatalogList() :Unable to get the Database List", he);
+ throw he;
+ }
+ return ret;
+ }
+ });
+
+ return dbs;
+ }
+
+ private List<String> getSchemas(String needle, List<String> catalogs, List<String> schemas) throws HadoopException {
+ List<String> ret = new ArrayList<>();
+ if (con != null) {
+ Statement stat = null;
+ ResultSet rs = null;
+ String sql = null;
+
+ try {
+ if (catalogs != null && !catalogs.isEmpty()) {
+ for (String catalog : catalogs) {
+ sql = "SHOW SCHEMAS FROM \"" + StringEscapeUtils.escapeSql(catalog) + "\"";
+
+ try {
+ if (needle != null && !needle.isEmpty() && !needle.equals("*")) {
+ sql += " LIKE '" + StringEscapeUtils.escapeSql(needle) + "%'";
+ }
+ stat = con.createStatement();
+ rs = stat.executeQuery(sql);
+ while (rs.next()) {
+ String schema = rs.getString(1);
+ if (schemas != null && schemas.contains(schema)) {
+ continue;
+ }
+ ret.add(schema);
+ }
+ } finally {
+ close(rs);
+ close(stat);
+ rs = null;
+ stat = null;
+ }
+ }
+ }
+ } catch (SQLTimeoutException sqlt) {
+ String msgDesc = "Time Out, Unable to execute SQL [" + sql
+ + "].";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ sqlt);
+ hdpException.generateResponseDataMap(false, getMessage(sqlt),
+ msgDesc + ERR_MSG, null, null);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoClient.getSchemas() Error : ", sqlt);
+ }
+ throw hdpException;
+ } catch (SQLException sqle) {
+ String msgDesc = "Unable to execute SQL [" + sql + "].";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ sqle);
+ hdpException.generateResponseDataMap(false, getMessage(sqle),
+ msgDesc + ERR_MSG, null, null);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoClient.getSchemas() Error : ", sqle);
+ }
+ throw hdpException;
+ }
+ }
+
+ return ret;
+ }
+
+ public List<String> getSchemaList(String needle, List<String> catalogs, List<String> schemas) throws HadoopException {
+ final String ndl = needle;
+ final List<String> cats = catalogs;
+ final List<String> shms = schemas;
+
+ List<String> schemaList = Subject.doAs(getLoginSubject(), new PrivilegedAction<List<String>>() {
+ @Override
+ public List<String> run() {
+ List<String> ret = null;
+ try {
+ ret = getSchemas(ndl, cats, shms);
+ } catch (HadoopException he) {
+ LOG.error("<== PrestoClient getSchemaList() :Unable to get the Schema List", he);
+ }
+ return ret;
+ }
+ });
+
+ return schemaList;
+ }
+
+ private List<String> getTables(String needle, List<String> catalogs, List<String> schemas, List<String> tables) throws HadoopException {
+ List<String> ret = new ArrayList<>();
+ if (con != null) {
+ Statement stat = null;
+ ResultSet rs = null;
+ String sql = null;
+
+ if (catalogs != null && !catalogs.isEmpty()
+ && schemas != null && !schemas.isEmpty()) {
+ try {
+ for (String catalog : catalogs) {
+ for (String schema : schemas) {
+ sql = "SHOW tables FROM \"" + StringEscapeUtils.escapeSql(catalog) + "\".\"" + StringEscapeUtils.escapeSql(schema) + "\"";
+ try {
+ if (needle != null && !needle.isEmpty() && !needle.equals("*")) {
+ sql += " LIKE '" + StringEscapeUtils.escapeSql(needle) + "%'";
+ }
+ stat = con.createStatement();
+ rs = stat.executeQuery(sql);
+ while (rs.next()) {
+ String table = rs.getString(1);
+ if (tables != null && tables.contains(table)) {
+ continue;
+ }
+ ret.add(table);
+ }
+ } finally {
+ close(rs);
+ close(stat);
+ rs = null;
+ stat = null;
+ }
+ }
+ }
+ } catch (SQLTimeoutException sqlt) {
+ String msgDesc = "Time Out, Unable to execute SQL [" + sql
+ + "].";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ sqlt);
+ hdpException.generateResponseDataMap(false, getMessage(sqlt),
+ msgDesc + ERR_MSG, null, null);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoClient.getTables() Error : ", sqlt);
+ }
+ throw hdpException;
+ } catch (SQLException sqle) {
+ String msgDesc = "Unable to execute SQL [" + sql + "].";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ sqle);
+ hdpException.generateResponseDataMap(false, getMessage(sqle),
+ msgDesc + ERR_MSG, null, null);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoClient.getTables() Error : ", sqle);
+ }
+ throw hdpException;
+ }
+ }
+ }
+ return ret;
+ }
+
+ public List<String> getTableList(String needle, List<String> catalogs, List<String> schemas, List<String> tables) throws HadoopException {
+ final String ndl = needle;
+ final List<String> cats = catalogs;
+ final List<String> shms = schemas;
+ final List<String> tbls = tables;
+
+ List<String> tableList = Subject.doAs(getLoginSubject(), new PrivilegedAction<List<String>>() {
+ @Override
+ public List<String> run() {
+ List<String> ret = null;
+ try {
+ ret = getTables(ndl, cats, shms, tbls);
+ } catch (HadoopException he) {
+ LOG.error("<== PrestoClient getTableList() :Unable to get the Column List", he);
+ throw he;
+ }
+ return ret;
+ }
+ });
+
+ return tableList;
+ }
+
+ private List<String> getColumns(String needle, List<String> catalogs, List<String> schemas, List<String> tables, List<String> columns) throws HadoopException {
+ List<String> ret = new ArrayList<>();
+ if (con != null) {
+ String regex = null;
+ ResultSet rs = null;
+ String sql = null;
+ Statement stat = null;
+
+ if (needle != null && !needle.isEmpty()) {
+ regex = needle;
+ }
+
+ if (catalogs != null && !catalogs.isEmpty()
+ && schemas != null && !schemas.isEmpty()
+ && tables != null && !tables.isEmpty()) {
+ try {
+ for (String catalog : catalogs) {
+ for (String schema : schemas) {
+ for (String table : tables) {
+ sql = "SHOW COLUMNS FROM \"" + StringEscapeUtils.escapeSql(catalog) + "\"." +
+ "\"" + StringEscapeUtils.escapeSql(schema) + "\"." +
+ "\"" + StringEscapeUtils.escapeSql(table) + "\"";
+
+ try {
+ stat = con.createStatement();
+ rs = stat.executeQuery(sql);
+ while (rs.next()) {
+ String column = rs.getString(1);
+ if (columns != null && columns.contains(column)) {
+ continue;
+ }
+ if (regex == null) {
+ ret.add(column);
+ } else if (FilenameUtils.wildcardMatch(column, regex)) {
+ ret.add(column);
+ }
+ }
+ } finally {
+ close(rs);
+ close(stat);
+ stat = null;
+ rs = null;
+ }
+ }
+ }
+ }
+ } catch (SQLTimeoutException sqlt) {
+ String msgDesc = "Time Out, Unable to execute SQL [" + sql
+ + "].";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ sqlt);
+ hdpException.generateResponseDataMap(false, getMessage(sqlt),
+ msgDesc + ERR_MSG, null, null);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoClient.getColumns() Error : ", sqlt);
+ }
+ throw hdpException;
+ } catch (SQLException sqle) {
+ String msgDesc = "Unable to execute SQL [" + sql + "].";
+ HadoopException hdpException = new HadoopException(msgDesc,
+ sqle);
+ hdpException.generateResponseDataMap(false, getMessage(sqle),
+ msgDesc + ERR_MSG, null, null);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoClient.getColumns() Error : ", sqle);
+ }
+ throw hdpException;
+ }
+ }
+ }
+ return ret;
+ }
+
+ public List<String> getColumnList(String needle, List<String> catalogs, List<String> schemas, List<String> tables, List<String> columns) throws HadoopException {
+ final String ndl = needle;
+ final List<String> cats = catalogs;
+ final List<String> shms = schemas;
+ final List<String> tbls = tables;
+ final List<String> cols = columns;
+
+ List<String> columnList = Subject.doAs(getLoginSubject(), new PrivilegedAction<List<String>>() {
+ @Override
+ public List<String> run() {
+ List<String> ret = null;
+ try {
+ ret = getColumns(ndl, cats, shms, tbls, cols);
+ } catch (HadoopException he) {
+ LOG.error("<== PrestoClient getColumnList() :Unable to get the Column List", he);
+ throw he;
+ }
+ return ret;
+ }
+ });
+ return columnList;
+ }
+
+ public static Map<String, Object> connectionTest(String serviceName,
+ Map<String, String> connectionProperties)
+ throws Exception {
+ PrestoClient client = null;
+ Map<String, Object> resp = new HashMap<String, Object>();
+
+ boolean status = false;
+
+ List<String> testResult = null;
+
+ try {
+ client = new PrestoClient(serviceName, connectionProperties);
+ if (client != null) {
+ testResult = client.getCatalogList("*", null);
+ if (testResult != null && testResult.size() != 0) {
+ status = true;
+ }
+ }
+
+ if (status) {
+ String msg = "Connection test succesful";
+ generateResponseDataMap(status, msg, msg, null, null, resp);
+ }
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ if (client != null) {
+ client.close();
+ }
+ }
+
+ return resp;
+ }
+
+ public void close() {
+ Subject.doAs(getLoginSubject(), new PrivilegedAction<Void>() {
+ public Void run() {
+ close(con);
+ return null;
+ }
+ });
+ }
+
+ private void close(Connection con) {
+ try {
+ if (con != null) {
+ con.close();
+ }
+ } catch (SQLException e) {
+ LOG.error("Unable to close Presto SQL connection", e);
+ }
+ }
+
+ public void close(Statement stat) {
+ try {
+ if (stat != null) {
+ stat.close();
+ }
+ } catch (SQLException e) {
+ LOG.error("Unable to close SQL statement", e);
+ }
+ }
+
+ public void close(ResultSet rs) {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ } catch (SQLException e) {
+ LOG.error("Unable to close ResultSet", e);
+ }
+ }
+}
diff --git a/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoConnectionManager.java b/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoConnectionManager.java
new file mode 100644
index 0000000..4a642ea
--- /dev/null
+++ b/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoConnectionManager.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.presto.client;
+
+import org.apache.log4j.Logger;
+import org.apache.ranger.plugin.util.TimedEventUtil;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+public class PrestoConnectionManager {
+ private static final Logger LOG = Logger.getLogger(PrestoConnectionManager.class);
+
+ protected ConcurrentMap<String, PrestoClient> prestoConnectionCache;
+ protected ConcurrentMap<String, Boolean> repoConnectStatusMap;
+
+ public PrestoConnectionManager() {
+ prestoConnectionCache = new ConcurrentHashMap<>();
+ repoConnectStatusMap = new ConcurrentHashMap<>();
+ }
+
+ public PrestoClient getPrestoConnection(final String serviceName, final String serviceType, final Map<String, String> configs) {
+ PrestoClient prestoClient = null;
+
+ if (serviceType != null) {
+ prestoClient = prestoConnectionCache.get(serviceName);
+ if (prestoClient == null) {
+ if (configs != null) {
+ final Callable<PrestoClient> connectPresto = new Callable<PrestoClient>() {
+ @Override
+ public PrestoClient call() throws Exception {
+ return new PrestoClient(serviceName, configs);
+ }
+ };
+ try {
+ prestoClient = TimedEventUtil.timedTask(connectPresto, 5, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ LOG.error("Error connecting to Presto repository: " +
+ serviceName + " using config: " + configs, e);
+ }
+
+ PrestoClient oldClient = null;
+ if (prestoClient != null) {
+ oldClient = prestoConnectionCache.putIfAbsent(serviceName, prestoClient);
+ } else {
+ oldClient = prestoConnectionCache.get(serviceName);
+ }
+
+ if (oldClient != null) {
+ if (prestoClient != null) {
+ prestoClient.close();
+ }
+ prestoClient = oldClient;
+ }
+ repoConnectStatusMap.put(serviceName, true);
+ } else {
+ LOG.error("Connection Config not defined for asset :"
+ + serviceName, new Throwable());
+ }
+ } else {
+ try {
+ prestoClient.getCatalogList("*", null);
+ } catch (Exception e) {
+ prestoConnectionCache.remove(serviceName);
+ prestoClient.close();
+ prestoClient = getPrestoConnection(serviceName, serviceType, configs);
+ }
+ }
+ } else {
+ LOG.error("Asset not found with name " + serviceName, new Throwable());
+ }
+ return prestoClient;
+ }
+}
diff --git a/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoResourceManager.java b/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoResourceManager.java
new file mode 100644
index 0000000..008bf0f
--- /dev/null
+++ b/plugin-presto/src/main/java/org/apache/ranger/services/presto/client/PrestoResourceManager.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.presto.client;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.apache.ranger.plugin.util.TimedEventUtil;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+public class PrestoResourceManager {
+ private static final Log LOG = LogFactory.getLog(PrestoResourceManager.class);
+
+ private static final String CATALOG = "catalog";
+ private static final String SCHEMA = "schema";
+ private static final String TABLE = "table";
+ private static final String COLUMN = "column";
+
+
+ public static Map<String, Object> connectionTest(String serviceName, Map<String, String> configs) throws Exception {
+ Map<String, Object> ret = null;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> PrestoResourceMgr.connectionTest ServiceName: " + serviceName + "Configs" + configs);
+ }
+
+ try {
+ ret = PrestoClient.connectionTest(serviceName, configs);
+ } catch (Exception e) {
+ LOG.error("<== PrestoResourceManager.connectionTest Error: " + e);
+ throw e;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoResourceManager.connectionTest Result : " + ret);
+ }
+
+ return ret;
+ }
+
+ public static List<String> getPrestoResources(String serviceName, String serviceType, Map<String, String> configs, ResourceLookupContext context) throws Exception {
+
+ String userInput = context.getUserInput();
+ String resource = context.getResourceName();
+ Map<String, List<String>> resourceMap = context.getResources();
+ List<String> resultList = null;
+ List<String> catalogList = null;
+ List<String> schemaList = null;
+ List<String> tableList = null;
+ List<String> columnList = null;
+ String catalogName = null;
+ String schemaName = null;
+ String tableName = null;
+ String columnName = null;
+
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== PrestoResourceMgr.getPrestoResources() UserInput: \"" + userInput + "\" resource : " + resource + " resourceMap: " + resourceMap);
+ }
+
+ if (userInput != null && resource != null) {
+ if (resourceMap != null && !resourceMap.isEmpty()) {
+ catalogList = resourceMap.get(CATALOG);
+ schemaList = resourceMap.get(SCHEMA);
+ tableList = resourceMap.get(TABLE);
+ columnList = resourceMap.get(COLUMN);
+ }
+ switch (resource.trim().toLowerCase()) {
+ case CATALOG:
+ catalogName = userInput;
+ break;
+ case SCHEMA:
+ schemaName = userInput;
+ case TABLE:
+ tableName = userInput;
+ break;
+ case COLUMN:
+ columnName = userInput;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (serviceName != null && userInput != null) {
+ try {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> PrestoResourceMgr.getPrestoResources() UserInput: " + userInput + " configs: " + configs + " catalogList: " + catalogList + " tableList: "
+ + tableList + " columnList: " + columnList);
+ }
+
+ final PrestoClient prestoClient = new PrestoConnectionManager().getPrestoConnection(serviceName, serviceType, configs);
+
+ Callable<List<String>> callableObj = null;
+
+ final String finalCatalogName;
+ final String finalSchemaName;
+ final String finalTableName;
+ final String finalColumnName;
+
+ final List<String> finalCatalogList = catalogList;
+ final List<String> finalSchemaList = schemaList;
+ final List<String> finalTableList = tableList;
+ final List<String> finalColumnList = columnList;
+
+ if (prestoClient != null) {
+ if (catalogName != null && !catalogName.isEmpty()) {
+ finalCatalogName = catalogName;
+ callableObj = new Callable<List<String>>() {
+ @Override
+ public List<String> call() throws Exception {
+ return prestoClient.getCatalogList(finalCatalogName, finalCatalogList);
+ }
+ };
+ } else if (schemaName != null && !schemaName.isEmpty()) {
+ finalSchemaName = schemaName;
+ callableObj = new Callable<List<String>>() {
+ @Override
+ public List<String> call() throws Exception {
+ return prestoClient.getSchemaList(finalSchemaName, finalCatalogList, finalSchemaList);
+ }
+ };
+ } else if (tableName != null && !tableName.isEmpty()) {
+ finalTableName = tableName;
+ callableObj = new Callable<List<String>>() {
+ @Override
+ public List<String> call() throws Exception {
+ return prestoClient.getTableList(finalTableName, finalCatalogList, finalSchemaList, finalTableList);
+ }
+ };
+ } else if (columnName != null && !columnName.isEmpty()) {
+ // Column names are matched by the wildcardmatcher
+ columnName += "*";
+ finalColumnName = columnName;
+ callableObj = new Callable<List<String>>() {
+ @Override
+ public List<String> call() throws Exception {
+ return prestoClient.getColumnList(finalColumnName, finalCatalogList, finalSchemaList, finalTableList, finalColumnList);
+ }
+ };
+ }
+ if (callableObj != null) {
+ synchronized (prestoClient) {
+ resultList = TimedEventUtil.timedTask(callableObj, 5, TimeUnit.SECONDS);
+ }
+ } else {
+ LOG.error("Could not initiate a PrestoClient timedTask");
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Unable to get Presto resource", e);
+ throw e;
+ }
+ }
+ return resultList;
+ }
+}
diff --git a/pom.xml b/pom.xml
index 40b053b..48cde0a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -158,6 +158,7 @@
<noggit.version>0.8</noggit.version>
<owasp-java-html-sanitizer.version>r239</owasp-java-html-sanitizer.version>
<paranamer.version>2.3</paranamer.version>
+ <presto.version>310</presto.version>
<poi.version>3.17</poi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<protobuf-java.version>2.5.0</protobuf-java.version>
@@ -184,6 +185,12 @@
<kstruct.gethostname4j.version>0.0.2</kstruct.gethostname4j.version>
<jna.version>5.2.0</jna.version>
<jna-platform.version>5.2.0</jna-platform.version>
+ <!-- presto plugin deps -->
+ <presto.airlift.version>0.178</presto.airlift.version>
+ <presto.bval-jsr.version>2.0.0</presto.bval-jsr.version>
+ <presto.guice.version>4.2.2</presto.guice.version>
+ <presto.guava.version>26.0-jre</presto.guava.version>
+ <presto.validation-api.version>2.0.1.Final</presto.validation-api.version>
</properties>
<profiles>
<profile>
@@ -211,6 +218,7 @@
<module>plugin-solr</module>
<module>plugin-nifi</module>
<module>plugin-nifi-registry</module>
+ <module>plugin-presto</module>
<module>ugsync</module>
<module>ugsync/ldapconfigchecktool/ldapconfigcheck</module>
<module>unixauthclient</module>
@@ -229,6 +237,7 @@
<module>ranger-solr-plugin-shim</module>
<module>ranger-atlas-plugin-shim</module>
<module>ranger-kms-plugin-shim</module>
+ <module>ranger-presto-plugin-shim</module>
<module>ranger-examples</module>
<module>ranger-tools</module>
<module>plugin-atlas</module>
@@ -265,6 +274,7 @@
<descriptor>src/main/assembly/plugin-sqoop.xml</descriptor>
<descriptor>src/main/assembly/plugin-kylin.xml</descriptor>
<descriptor>src/main/assembly/plugin-elasticsearch.xml</descriptor>
+ <descriptor>src/main/assembly/plugin-presto.xml</descriptor>
</descriptors>
</configuration>
</plugin>
@@ -623,6 +633,33 @@
</build>
</profile>
<profile>
+ <id>ranger-presto-plugin</id>
+ <modules>
+ <module>agents-audit</module>
+ <module>agents-common</module>
+ <module>agents-cred</module>
+ <module>agents-installer</module>
+ <module>credentialbuilder</module>
+ <module>ranger-plugin-classloader</module>
+ <module>ranger-util</module>
+ <module>plugin-presto</module>
+ <module>ranger-presto-plugin-shim</module>
+ </modules>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.2-beta-5</version>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/plugin-presto.xml</descriptor>
+ </descriptors>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
<id>linux</id>
<activation>
<os>
@@ -676,6 +713,8 @@
<module>ranger-kylin-plugin-shim</module>
<module>plugin-elasticsearch</module>
<module>ranger-elasticsearch-plugin-shim</module>
+ <module>plugin-presto</module>
+ <module>ranger-presto-plugin-shim</module>
<module>unixauthnative</module>
</modules>
<build>
@@ -704,6 +743,7 @@
<descriptor>src/main/assembly/plugin-sqoop.xml</descriptor>
<descriptor>src/main/assembly/plugin-kylin.xml</descriptor>
<descriptor>src/main/assembly/plugin-elasticsearch.xml</descriptor>
+ <descriptor>src/main/assembly/plugin-presto.xml</descriptor>
</descriptors>
</configuration>
</plugin>
diff --git a/ranger-presto-plugin-shim/pom.xml b/ranger-presto-plugin-shim/pom.xml
new file mode 100644
index 0000000..91ca8e8
--- /dev/null
+++ b/ranger-presto-plugin-shim/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>ranger-presto-plugin-shim</artifactId>
+ <name>Presto Security Plugin Shim</name>
+ <description>Presto Security Plugin Shim</description>
+ <packaging>jar</packaging>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <parent>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.prestosql</groupId>
+ <artifactId>presto-spi</artifactId>
+ <version>${presto.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugin-classloader</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.airlift</groupId>
+ <artifactId>bootstrap</artifactId>
+ <version>${presto.airlift.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.airlift</groupId>
+ <artifactId>log</artifactId>
+ <version>${presto.airlift.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.airlift</groupId>
+ <artifactId>configuration</artifactId>
+ <version>${presto.airlift.version}</version>
+ </dependency>
+
+ <!-- for the assembly -->
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${presto.guava.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <version>${presto.guice.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <version>${presto.validation-api.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.bval</groupId>
+ <artifactId>bval-jsr</artifactId>
+ <version>${presto.bval-jsr.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>${httpcomponents.httpcore.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.zookeeper</groupId>
+ <artifactId>zookeeper</artifactId>
+ <version>${zookeeper.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/PrestoRangerPlugin.java b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/PrestoRangerPlugin.java
new file mode 100644
index 0000000..fe70772
--- /dev/null
+++ b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/PrestoRangerPlugin.java
@@ -0,0 +1,32 @@
+/*
+ * 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 org.apache.ranger.authorization.presto.authorizer;
+
+import io.prestosql.spi.Plugin;
+import io.prestosql.spi.security.SystemAccessControlFactory;
+
+import java.util.ArrayList;
+
+public class PrestoRangerPlugin
+ implements Plugin
+{
+ @Override
+ public Iterable<SystemAccessControlFactory> getSystemAccessControlFactories()
+ {
+ ArrayList<SystemAccessControlFactory> list = new ArrayList<>();
+ SystemAccessControlFactory factory = new RangerSystemAccessControlFactory();
+ list.add(factory);
+ return list;
+ }
+}
diff --git a/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerConfig.java b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerConfig.java
new file mode 100644
index 0000000..67b0d24
--- /dev/null
+++ b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerConfig.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.authorization.presto.authorizer;
+
+import io.airlift.configuration.Config;
+import io.airlift.configuration.ConfigDescription;
+
+public class RangerConfig {
+ private String keytab;
+ private String principal;
+
+ public String getKeytab() { return keytab; }
+
+ @Config("ranger.keytab")
+ @ConfigDescription("Keytab for authentication against Ranger")
+ @SuppressWarnings("unused")
+ public RangerConfig setKeytab(String keytab) {
+ this.keytab = keytab;
+ return this;
+ }
+
+ public String getPrincipal() { return principal; }
+
+ @Config("ranger.principal")
+ @ConfigDescription("Principal for authentication against Ranger with keytab")
+ @SuppressWarnings("unused")
+ public RangerConfig setPrincipal(String principal) {
+ this.principal = principal;
+ return this;
+ }
+}
diff --git a/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControl.java b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControl.java
new file mode 100644
index 0000000..e89f646
--- /dev/null
+++ b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControl.java
@@ -0,0 +1,382 @@
+/*
+ * 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 org.apache.ranger.authorization.presto.authorizer;
+
+import io.prestosql.spi.connector.CatalogSchemaName;
+import io.prestosql.spi.connector.CatalogSchemaTableName;
+import io.prestosql.spi.connector.SchemaTableName;
+import io.prestosql.spi.security.AccessDeniedException;
+import io.prestosql.spi.security.Identity;
+import io.prestosql.spi.security.SystemAccessControl;
+import org.apache.ranger.plugin.classloader.RangerPluginClassLoader;
+
+import javax.inject.Inject;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+public class RangerSystemAccessControl
+ implements SystemAccessControl {
+ private static final String RANGER_PLUGIN_TYPE = "presto";
+ private static final String RANGER_PRESTO_AUTHORIZER_IMPL_CLASSNAME = "org.apache.ranger.authorization.presto.authorizer.RangerSystemAccessControl";
+
+ final private RangerPluginClassLoader rangerPluginClassLoader;
+ final private SystemAccessControl systemAccessControlImpl;
+
+ @Inject
+ public RangerSystemAccessControl(RangerConfig config) {
+ try {
+ rangerPluginClassLoader = RangerPluginClassLoader.getInstance(RANGER_PLUGIN_TYPE, this.getClass());
+
+ @SuppressWarnings("unchecked")
+ Class<SystemAccessControl> cls = (Class<SystemAccessControl>) Class.forName(RANGER_PRESTO_AUTHORIZER_IMPL_CLASSNAME, true, rangerPluginClassLoader);
+
+ activatePluginClassLoader();
+
+ Map<String, String> configMap = new HashMap<>();
+ if (config.getKeytab() != null && config.getPrincipal() != null) {
+ configMap.put("ranger.keytab", config.getKeytab());
+ configMap.put("ranger.principal", config.getPrincipal());
+ }
+ systemAccessControlImpl = cls.getDeclaredConstructor(Map.class).newInstance(configMap);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ deactivatePluginClassLoader();
+ }
+ }
+
+ @Override
+ public void checkCanSetUser(Optional<Principal> principal, String userName) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanSetUser(principal, userName);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denySetUser(principal, userName);
+ }
+ }
+
+ @Override
+ public void checkCanSetSystemSessionProperty(Identity identity, String propertyName) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanSetSystemSessionProperty(identity, propertyName);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denySetSystemSessionProperty(propertyName);
+ }
+ }
+
+ @Override
+ public void checkCanAccessCatalog(Identity identity, String catalogName) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanAccessCatalog(identity, catalogName);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyCatalogAccess(catalogName);
+ }
+ }
+
+ @Override
+ public Set<String> filterCatalogs(Identity identity, Set<String> catalogs) {
+ return catalogs;
+ }
+
+ @Override
+ public void checkCanCreateSchema(Identity identity, CatalogSchemaName schema) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanCreateSchema(identity, schema);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyCreateSchema(schema.getSchemaName());
+ }
+ }
+
+ @Override
+ public void checkCanDropSchema(Identity identity, CatalogSchemaName schema) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanDropSchema(identity, schema);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyDropSchema(schema.getSchemaName());
+ }
+ }
+
+ @Override
+ public void checkCanRenameSchema(Identity identity, CatalogSchemaName schema, String newSchemaName) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanRenameSchema(identity, schema, newSchemaName);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyRenameSchema(schema.getSchemaName(), newSchemaName);
+ }
+ }
+
+ @Override
+ public void checkCanShowSchemas(Identity identity, String catalogName) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanShowSchemas(identity, catalogName);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyShowSchemas();
+ }
+ }
+
+ @Override
+ public Set<String> filterSchemas(Identity identity, String catalogName, Set<String> schemaNames) {
+ return schemaNames;
+ }
+
+ @Override
+ public void checkCanCreateTable(Identity identity, CatalogSchemaTableName table) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanCreateTable(identity, table);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyCreateTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDropTable(Identity identity, CatalogSchemaTableName table) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanDropTable(identity, table);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyDropTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanRenameTable(Identity identity, CatalogSchemaTableName table, CatalogSchemaTableName newTable) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanRenameTable(identity, table, newTable);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyRenameTable(table.getSchemaTableName().getTableName(), newTable.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanShowTablesMetadata(Identity identity, CatalogSchemaName schema) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanShowTablesMetadata(identity, schema);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyShowTablesMetadata(schema.getSchemaName());
+ }
+ }
+
+ @Override
+ public Set<SchemaTableName> filterTables(Identity identity, String catalogName, Set<SchemaTableName> tableNames) {
+ return tableNames;
+ }
+
+ @Override
+ public void checkCanAddColumn(Identity identity, CatalogSchemaTableName table) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanAddColumn(identity, table);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyAddColumn(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDropColumn(Identity identity, CatalogSchemaTableName table) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanDropColumn(identity, table);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyDropColumn(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanRenameColumn(Identity identity, CatalogSchemaTableName table) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanRenameColumn(identity, table);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyRenameColumn(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanSelectFromColumns(Identity identity, CatalogSchemaTableName table, Set<String> columns) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanSelectFromColumns(identity, table, columns);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denySelectColumns(table.getSchemaTableName().getTableName(), columns);
+ }
+ }
+
+ @Override
+ public void checkCanInsertIntoTable(Identity identity, CatalogSchemaTableName table) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanInsertIntoTable(identity, table);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyInsertTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDeleteFromTable(Identity identity, CatalogSchemaTableName table) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanDeleteFromTable(identity, table);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyDeleteTable(table.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanCreateView(Identity identity, CatalogSchemaTableName view) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanCreateView(identity, view);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyCreateView(view.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanDropView(Identity identity, CatalogSchemaTableName view) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanDropView(identity, view);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyDropView(view.getSchemaTableName().getTableName());
+ }
+ }
+
+ @Override
+ public void checkCanCreateViewWithSelectFromColumns(Identity identity, CatalogSchemaTableName table, Set<String> columns) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanCreateViewWithSelectFromColumns(identity, table, columns);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denyCreateViewWithSelect(table.getSchemaTableName().getTableName(), identity);
+ }
+ }
+
+ @Override
+ public void checkCanSetCatalogSessionProperty(Identity identity, String catalogName, String propertyName) {
+ try {
+ activatePluginClassLoader();
+ systemAccessControlImpl.checkCanSetCatalogSessionProperty(identity, catalogName, propertyName);
+ } catch (AccessDeniedException e) {
+ deactivatePluginClassLoader();
+ throw e;
+ } catch (Exception e) {
+ deactivatePluginClassLoader();
+ AccessDeniedException.denySetCatalogSessionProperty(catalogName, propertyName);
+ }
+ }
+
+ private void activatePluginClassLoader() {
+ if (rangerPluginClassLoader != null) {
+ rangerPluginClassLoader.activate();
+ }
+ }
+
+ private void deactivatePluginClassLoader() {
+ if (rangerPluginClassLoader != null) {
+ rangerPluginClassLoader.deactivate();
+ }
+ }
+}
diff --git a/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControlFactory.java b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControlFactory.java
new file mode 100644
index 0000000..e446ada
--- /dev/null
+++ b/ranger-presto-plugin-shim/src/main/java/org/apache/ranger/authorization/presto/authorizer/RangerSystemAccessControlFactory.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.apache.ranger.authorization.presto.authorizer;
+
+import com.google.inject.Injector;
+import com.google.inject.Scopes;
+import io.airlift.bootstrap.Bootstrap;
+import io.prestosql.spi.security.SystemAccessControl;
+import io.prestosql.spi.security.SystemAccessControlFactory;
+
+import java.util.Map;
+
+import static com.google.common.base.Throwables.throwIfUnchecked;
+import static io.airlift.configuration.ConfigBinder.configBinder;
+import static java.util.Objects.requireNonNull;
+
+public class RangerSystemAccessControlFactory
+ implements SystemAccessControlFactory {
+ private static final String NAME = "ranger";
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public SystemAccessControl create(Map<String, String> config) {
+ requireNonNull(config, "config is null");
+
+ try {
+ Bootstrap app = new Bootstrap(
+ binder -> {
+ configBinder(binder).bindConfig(RangerConfig.class);
+ binder.bind(RangerSystemAccessControl.class).in(Scopes.SINGLETON);
+ }
+ );
+
+ Injector injector = app
+ .strictConfig()
+ .doNotInitializeLogging()
+ .setRequiredConfigurationProperties(config)
+ .initialize();
+
+ return injector.getInstance(RangerSystemAccessControl.class);
+ } catch (Exception e) {
+ throwIfUnchecked(e);
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/ranger-presto-plugin-shim/src/main/resources/META-INF/services/io.prestosql.spi.Plugin b/ranger-presto-plugin-shim/src/main/resources/META-INF/services/io.prestosql.spi.Plugin
new file mode 100644
index 0000000..ff40776
--- /dev/null
+++ b/ranger-presto-plugin-shim/src/main/resources/META-INF/services/io.prestosql.spi.Plugin
@@ -0,0 +1,15 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+org.apache.ranger.authorization.presto.authorizer.PrestoRangerPlugin
diff --git a/src/main/assembly/admin-web.xml b/src/main/assembly/admin-web.xml
index c862155..670ec1b 100644
--- a/src/main/assembly/admin-web.xml
+++ b/src/main/assembly/admin-web.xml
@@ -403,6 +403,27 @@
<include>org.apache.ranger:ranger-elasticsearch-plugin</include>
</includes>
</moduleSet>
+ <moduleSet>
+ <binaries>
+ <includeDependencies>true</includeDependencies>
+ <outputDirectory>/ews/webapp/WEB-INF/classes/ranger-plugins/presto</outputDirectory>
+ <unpack>false</unpack>
+ <directoryMode>755</directoryMode>
+ <fileMode>644</fileMode>
+ <dependencySets>
+ <dependencySet>
+ <includes>
+ <include>io.prestosql:presto-spi:jar:${presto.version}</include>
+ <include>io.prestosql:presto-jdbc:jar:${presto.version}</include>
+ </includes>
+ </dependencySet>
+ </dependencySets>
+ </binaries>
+ <includes>
+ <include>org.apache.ranger:ranger-presto-plugin</include>
+ </includes>
+ </moduleSet>
+
</moduleSets>
<fileSets>
diff --git a/src/main/assembly/plugin-presto.xml b/src/main/assembly/plugin-presto.xml
new file mode 100644
index 0000000..8063a9d
--- /dev/null
+++ b/src/main/assembly/plugin-presto.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+ <id>presto-plugin</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <baseDirectory>${project.name}-${project.version}-presto-plugin</baseDirectory>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <moduleSets>
+ <moduleSet>
+ <binaries>
+ <includeDependencies>false</includeDependencies>
+ <unpack>false</unpack>
+ <directoryMode>755</directoryMode>
+ <fileMode>644</fileMode>
+ <outputDirectory>/lib</outputDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/lib</outputDirectory>
+ <unpack>false</unpack>
+ <includes>
+ <include>com.google.inject:guice:jar:${presto.guice.version}</include>
+ <include>com.google.guava:guava:jar:${presto.guava.version}</include>
+ <include>io.airlift:bootstrap:jar:${presto.airlift.version}</include>
+ <include>io.airlift:log:jar:${presto.airlift.version}</include>
+ <include>io.airlift:log-manager:jar:${presto.airlift.version}</include>
+ <include>io.airlift:configuration:jar:${presto.airlift.version}</include>
+ <include>javax.validation:validation-api:jar:${presto.validation-api.version}</include>
+ <include>javax.inject:javax.inject:jar:${javax-inject.version}</include>
+ <include>org.apache.bval:bval-jsr:jar:${presto.bval-jsr.version}</include>
+ <include>org.slf4j:slf4j-api:jar:${slf4j-api.version}</include>
+ </includes>
+ </dependencySet>
+ </dependencySets>
+ </binaries>
+ <includes>
+ <include>org.apache.ranger:ranger-presto-plugin-shim</include>
+ <include>org.apache.ranger:ranger-plugin-classloader</include>
+ </includes>
+ </moduleSet>
+
+ <moduleSet>
+ <binaries>
+ <includeDependencies>false</includeDependencies>
+ <unpack>false</unpack>
+ <directoryMode>755</directoryMode>
+ <fileMode>644</fileMode>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/lib/ranger-presto-plugin-impl</outputDirectory>
+ <unpack>false</unpack>
+ <includes>
+ <include>com.google.code.gson:gson*</include>
+ <include>org.eclipse.persistence:eclipselink</include>
+ <include>org.eclipse.persistence:javax.persistence</include>
+ <include>org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version}</include>
+ <include>org.apache.httpcomponents:httpclient:jar:${httpcomponents.httpclient.version}</include>
+ <include>org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version}</include>
+ <include>org.noggit:noggit:jar:${noggit.version}</include>
+ <include>org.apache.solr:solr-solrj</include>
+ <include>com.sun.jersey:jersey-core</include>
+ <include>com.sun.jersey:jersey-server</include>
+ <include>commons-cli:commons-cli</include>
+ <include>commons-collections:commons-collections</include>
+ <include>org.apache.commons:commons-configuration2:jar:${commons.configuration.version}</include>
+ <include>commons-io:commons-io:jar:${commons.io.version}</include>
+ <include>commons-lang:commons-lang:jar:${commons.lang.version}</include>
+ <include>commons-logging:commons-logging:jar:${commons.logging.version}</include>
+ <include>com.google.guava:guava:jar:${google.guava.version}</include>
+ <include>org.apache.hadoop:hadoop-common:jar:${hadoop.version}</include>
+ <include>org.apache.hadoop:hadoop-auth:jar:${hadoop.version}</include>
+ <include>org.apache.ranger:ranger-plugins-cred</include>
+ <include>org.apache.ranger:credentialbuilder</include>
+ <include>org.codehaus.woodstox:stax2-api</include>
+ <include>com.fasterxml.woodstox:woodstox-core</include>
+ <include>org.apache.htrace:htrace-core4</include>
+ <include>com.sun.jersey:jersey-bundle</include>
+ <include>com.sun.jersey:jersey-json</include>
+ <include>org.codehaus.jackson:jackson-core-asl</include>
+ <include>org.codehaus.jackson:jackson-jaxrs</include>
+ <include>org.codehaus.jackson:jackson-mapper-asl</include>
+ <include>org.codehaus.jackson:jackson-xc</include>
+ <include>org.apache.zookeeper:zookeeper:jar:${zookeeper.version}</include>
+ </includes>
+ </dependencySet>
+ </dependencySets>
+ <outputDirectory>/lib/ranger-presto-plugin-impl</outputDirectory>
+ </binaries>
+ <includes>
+ <include>org.apache.ranger:ranger-plugins-audit</include>
+ <include>org.apache.ranger:ranger-plugins-cred</include>
+ <include>org.apache.ranger:ranger-plugins-common</include>
+ <include>org.apache.ranger:ranger-presto-plugin</include>
+ </includes>
+ </moduleSet>
+ <moduleSet>
+ <binaries>
+ <includeDependencies>true</includeDependencies>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/install/lib</outputDirectory>
+ <unpack>false</unpack>
+ <includes>
+ <include>commons-cli:commons-cli</include>
+ <include>commons-collections:commons-collections</include>
+ <include>org.apache.commons:commons-configuration2:jar:${commons.configuration.version}</include>
+ <include>commons-io:commons-io:jar:${commons.io.version}</include>
+ <include>commons-lang:commons-lang</include>
+ <include>commons-logging:commons-logging:jar:${commons.logging.version}</include>
+ <include>com.google.guava:guava:jar:${google.guava.version}</include>
+ <include>org.slf4j:slf4j-api:jar:${slf4j-api.version}</include>
+ <include>org.apache.hadoop:hadoop-common:jar:${hadoop.version}</include>
+ <include>org.apache.hadoop:hadoop-auth:jar:${hadoop.version}</include>
+ <include>org.codehaus.woodstox:stax2-api</include>
+ <include>com.fasterxml.woodstox:woodstox-core</include>
+ <include>org.apache.htrace:htrace-core4</include>
+ </includes>
+ </dependencySet>
+ </dependencySets>
+ <outputDirectory>/install/lib</outputDirectory>
+ <unpack>false</unpack>
+ </binaries>
+ <includes>
+ <include>org.apache.ranger:ranger-plugins-installer</include>
+ <include>org.apache.ranger:credentialbuilder</include>
+ </includes>
+ </moduleSet>
+ </moduleSets>
+ <fileSets>
+ <!-- conf.templates for enable -->
+ <fileSet>
+ <outputDirectory>/install/conf.templates/enable</outputDirectory>
+ <directory>plugin-presto/conf</directory>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ <fileMode>700</fileMode>
+ </fileSet>
+ <fileSet>
+ <outputDirectory>/install/conf.templates/disable</outputDirectory>
+ <directory>plugin-presto/disable-conf</directory>
+ <fileMode>700</fileMode>
+ </fileSet>
+ <fileSet>
+ <outputDirectory>/install/conf.templates/default</outputDirectory>
+ <directory>plugin-presto/template</directory>
+ <fileMode>700</fileMode>
+ </fileSet>
+ <!-- version file -->
+ <fileSet>
+ <outputDirectory>/</outputDirectory>
+ <directory>${project.build.outputDirectory}</directory>
+ <includes>
+ <include>version</include>
+ </includes>
+ <fileMode>444</fileMode>
+ </fileSet>
+ </fileSets>
+ <!-- enable/disable script for Plugin -->
+ <files>
+ <file>
+ <source>agents-common/scripts/enable-agent.sh</source>
+ <outputDirectory>/</outputDirectory>
+ <destName>enable-presto-plugin.sh</destName>
+ <fileMode>755</fileMode>
+ </file>
+ <file>
+ <source>agents-common/scripts/enable-agent.sh</source>
+ <outputDirectory>/</outputDirectory>
+ <destName>disable-presto-plugin.sh</destName>
+ <fileMode>755</fileMode>
+ </file>
+ <file>
+ <source>plugin-presto/scripts/install.properties</source>
+ <outputDirectory>/</outputDirectory>
+ <destName>install.properties</destName>
+ <fileMode>755</fileMode>
+ </file>
+ <file>
+ <source>security-admin/scripts/ranger_credential_helper.py</source>
+ <outputDirectory>/</outputDirectory>
+ <fileMode>755</fileMode>
+ </file>
+ </files>
+</assembly>