RANGER-1672:Ranger supports plugin to enable, monitor and manage apache kylin
Signed-off-by: peng.jianhua <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/2b1143ab Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/2b1143ab Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/2b1143ab Branch: refs/heads/master Commit: 2b1143abac2a665bbefbbfcd17b57390094a7a2b Parents: 8888b62 Author: zhangqiang2 <[email protected]> Authored: Mon Mar 5 16:07:34 2018 +0800 Committer: peng.jianhua <[email protected]> Committed: Sun Mar 11 08:17:47 2018 +0800 ---------------------------------------------------------------------- agents-common/scripts/enable-agent.sh | 32 ++- .../plugin/store/EmbeddedServiceDefsUtil.java | 9 +- .../ranger/plugin/util/PasswordUtils.java | 15 + .../service-defs/ranger-servicedef-kylin.json | 110 ++++++++ plugin-kylin/.gitignore | 1 + .../conf/ranger-kylin-audit-changes.cfg | 65 +++++ plugin-kylin/conf/ranger-kylin-audit.xml | 271 ++++++++++++++++++ .../conf/ranger-kylin-security-changes.cfg | 28 ++ plugin-kylin/conf/ranger-kylin-security.xml | 83 ++++++ .../conf/ranger-policymgr-ssl-changes.cfg | 21 ++ plugin-kylin/conf/ranger-policymgr-ssl.xml | 49 ++++ plugin-kylin/pom.xml | 77 +++++ plugin-kylin/scripts/install.properties | 140 +++++++++ .../kylin/authorizer/RangerKylinAuthorizer.java | 182 ++++++++++++ .../services/kylin/RangerServiceKylin.java | 89 ++++++ .../services/kylin/client/KylinClient.java | 282 +++++++++++++++++++ .../services/kylin/client/KylinResourceMgr.java | 97 +++++++ .../client/json/model/KylinProjectResponse.java | 109 +++++++ pom.xml | 4 + ranger-kylin-plugin-shim/.gitignore | 1 + ranger-kylin-plugin-shim/pom.xml | 72 +++++ .../kylin/authorizer/RangerKylinAuthorizer.java | 121 ++++++++ src/main/assembly/admin-web.xml | 13 + src/main/assembly/plugin-kylin.xml | 159 +++++++++++ 24 files changed, 2026 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/agents-common/scripts/enable-agent.sh ---------------------------------------------------------------------- diff --git a/agents-common/scripts/enable-agent.sh b/agents-common/scripts/enable-agent.sh index 7033f79..ce0dc8c 100755 --- a/agents-common/scripts/enable-agent.sh +++ b/agents-common/scripts/enable-agent.sh @@ -208,6 +208,8 @@ elif [ "${HCOMPONENT_NAME}" = "hadoop" ] || HCOMPONENT_LIB_DIR=${HCOMPONENT_INSTALL_DIR}/share/hadoop/hdfs/lib elif [ "${HCOMPONENT_NAME}" = "sqoop" ]; then HCOMPONENT_LIB_DIR=${HCOMPONENT_INSTALL_DIR}/server/lib +elif [ "${HCOMPONENT_NAME}" = "kylin" ]; then + HCOMPONENT_LIB_DIR=${HCOMPONENT_INSTALL_DIR}/tomcat/webapps/kylin/WEB-INF/lib fi HCOMPONENT_CONF_DIR=${HCOMPONENT_INSTALL_DIR}/conf @@ -714,9 +716,6 @@ then updatePropertyToFile atlas.authorizer.impl $authName ${fn} fi fi -# -# Set notice to restart the ${HCOMPONENT_NAME} -# if [ "${HCOMPONENT_NAME}" = "sqoop" ] then @@ -741,6 +740,33 @@ then fi fi +if [ "${HCOMPONENT_NAME}" = "kylin" ] +then + if [ "${action}" = "enable" ] + then + authName="org.apache.ranger.authorization.kylin.authorizer.RangerKylinAuthorizer" + else + authName="" + fi + + dt=`date '+%Y%m%d%H%M%S'` + fn=`ls ${HCOMPONENT_CONF_DIR}/kylin.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 kylin.server.external-acl-provider $authName ${fn} + fi +fi + +# +# Set notice to restart the ${HCOMPONENT_NAME} +# + echo "Ranger Plugin for ${HCOMPONENT_NAME} has been ${action}d. Please restart ${HCOMPONENT_NAME} to ensure that changes are effective." exit 0 http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java ---------------------------------------------------------------------- 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 899bcac..5e74da8 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 - private static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,sqoop"; + private static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,sqoop,kylin"; private static final String PROPERTY_SUPPORTED_SERVICE_DEFS = "ranger.supportedcomponents"; private Set<String> supportedServiceDefs; public static final String EMBEDDED_SERVICEDEF_TAG_NAME = "tag"; @@ -65,6 +65,7 @@ public class EmbeddedServiceDefsUtil { public static final String EMBEDDED_SERVICEDEF_ATLAS_NAME = "atlas"; public static final String EMBEDDED_SERVICEDEF_WASB_NAME = "wasb"; public static final String EMBEDDED_SERVICEDEF_SQOOP_NAME = "sqoop"; + public static final String EMBEDDED_SERVICEDEF_KYLIN_NAME = "kylin"; public static final String PROPERTY_CREATE_EMBEDDED_SERVICE_DEFS = "ranger.service.store.create.embedded.service-defs"; @@ -96,6 +97,7 @@ public class EmbeddedServiceDefsUtil { private RangerServiceDef atlasServiceDef; private RangerServiceDef wasbServiceDef; private RangerServiceDef sqoopServiceDef; + private RangerServiceDef kylinServiceDef; private RangerServiceDef tagServiceDef; @@ -136,6 +138,7 @@ public class EmbeddedServiceDefsUtil { tagServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_TAG_NAME); wasbServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_WASB_NAME); sqoopServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_SQOOP_NAME); + kylinServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_KYLIN_NAME); // Ensure that tag service def is updated with access types of all service defs store.updateTagServiceDefForAccessTypes(); @@ -194,6 +197,10 @@ public class EmbeddedServiceDefsUtil { return getId(sqoopServiceDef); } + public long getKylinServiceDefId() { + return getId(kylinServiceDef); + } + public long getTagServiceDefId() { return getId(tagServiceDef); } public long getWasbServiceDefId() { return getId(wasbServiceDef); } http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java index 6ba42d4..6480b17 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java @@ -149,4 +149,19 @@ public class PasswordUtils { } return ret; } + + public static String getDecryptPassword(String password) { + String decryptedPwd = null; + try { + decryptedPwd = decryptPassword(password); + } catch (Exception ex) { + LOG.warn("Password decryption failed, trying original password string."); + decryptedPwd = null; + } finally { + if (decryptedPwd == null) { + decryptedPwd = password; + } + } + return decryptedPwd; + } } http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/agents-common/src/main/resources/service-defs/ranger-servicedef-kylin.json ---------------------------------------------------------------------- diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-kylin.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-kylin.json new file mode 100644 index 0000000..cda3526 --- /dev/null +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-kylin.json @@ -0,0 +1,110 @@ +{ + "id":12, + "name": "kylin", + "implClass": "org.apache.ranger.services.kylin.RangerServiceKylin", + "label": "KYLIN", + "description": "KYLIN", + "guid": "88ab8471-3e27-40c2-8bd8-458b5b1a9b25", + "resources": + [ + { + "itemId": 1, + "name": "project", + "type": "string", + "level": 10, + "parent": "", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard":true, "ignoreCase":true}, + "validationRegEx":"", + "validationMessage": "", + "uiHint":"", + "label": "Kylin Project", + "description": "Kylin Project" + } + ], + + "accessTypes": + [ + { + "itemId": 1, + "name": "QUERY", + "label": "QUERY" + }, + + { + "itemId": 2, + "name": "OPERATION", + "label": "OPERATION" + }, + + { + "itemId": 3, + "name": "MANAGEMENT", + "label": "MANAGEMENT" + }, + + { + "itemId": 4, + "name": "ADMIN", + "label": "ADMIN" + } + ], + + "configs": + [ + { + "itemId": 1, + "name": "username", + "type": "string", + "mandatory": true, + "validationRegEx":"", + "validationMessage": "", + "uiHint":"", + "label": "Username" + }, + + { + "itemId": 2, + "name": "password", + "type": "password", + "mandatory": true, + "validationRegEx":"", + "validationMessage": "", + "uiHint":"", + "label": "Password" + }, + + { + "itemId": 3, + "name": "kylin.url", + "type": "string", + "mandatory": true, + "defaultValue": "", + "validationRegEx":"", + "validationMessage": "", + "uiHint":"{\"TextFieldWithIcon\":true, \"info\": \"eg. 'http://<ipaddr>:7070'\"}", + "label": "Kylin URL" + } + + ], + "options": { "enableDenyAndExceptionsInPolicies": "false" }, + + "enums": + [ + + ], + + "contextEnrichers": + [ + + ], + + "policyConditions": + [ + + ] +} http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/.gitignore ---------------------------------------------------------------------- diff --git a/plugin-kylin/.gitignore b/plugin-kylin/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/plugin-kylin/.gitignore @@ -0,0 +1 @@ +/target/ http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/conf/ranger-kylin-audit-changes.cfg ---------------------------------------------------------------------- diff --git a/plugin-kylin/conf/ranger-kylin-audit-changes.cfg b/plugin-kylin/conf/ranger-kylin-audit-changes.cfg new file mode 100644 index 0000000..8071e7b --- /dev/null +++ b/plugin-kylin/conf/ranger-kylin-audit-changes.cfg @@ -0,0 +1,65 @@ +# 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.kafka.is.enabled %XAAUDIT.KAFKA.IS_ENABLED% mod create-if-not-exists +#xasecure.audit.kafka.is.async %XAAUDIT.KAFKA.IS_ASYNC% mod create-if-not-exists +#xasecure.audit.kafka.async.max.queue.size %XAAUDIT.KAFKA.MAX_QUEUE_SIZE% mod create-if-not-exists +#xasecure.audit.kafka.async.max.flush.interval.ms %XAAUDIT.KAFKA.MAX_FLUSH_INTERVAL_MS% mod create-if-not-exists +#xasecure.audit.kafka.broker_list %XAAUDIT.KAFKA.BROKER_LIST% mod create-if-not-exists +#xasecure.audit.kafka.topic_name %XAAUDIT.KAFKA.TOPIC_NAME% mod create-if-not-exists + +xasecure.audit.solr.is.enabled %XAAUDIT.SOLR.IS_ENABLED% mod create-if-not-exists +xasecure.audit.solr.async.max.queue.size %XAAUDIT.SOLR.MAX_QUEUE_SIZE% mod create-if-not-exists +xasecure.audit.solr.async.max.flush.interval.ms %XAAUDIT.SOLR.MAX_FLUSH_INTERVAL_MS% mod create-if-not-exists +xasecure.audit.solr.solr_url %XAAUDIT.SOLR.SOLR_URL% mod create-if-not-exists + +#V3 configuration +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 http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/conf/ranger-kylin-audit.xml ---------------------------------------------------------------------- diff --git a/plugin-kylin/conf/ranger-kylin-audit.xml b/plugin-kylin/conf/ranger-kylin-audit.xml new file mode 100644 index 0000000..94fba58 --- /dev/null +++ b/plugin-kylin/conf/ranger-kylin-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/kylindev/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/kylin/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/kylin/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://[email protected]</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> + + <!-- Kafka audit provider configuration --> + <property> + <name>xasecure.audit.kafka.is.enabled</name> + <value>false</value> + </property> + + <property> + <name>xasecure.audit.kafka.async.max.queue.size</name> + <value>1</value> + </property> + + <property> + <name>xasecure.audit.kafka.async.max.flush.interval.ms</name> + <value>1000</value> + </property> + + <property> + <name>xasecure.audit.kafka.broker_list</name> + <value>localhost:9092</value> + </property> + + <property> + <name>xasecure.audit.kafka.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> http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/conf/ranger-kylin-security-changes.cfg ---------------------------------------------------------------------- diff --git a/plugin-kylin/conf/ranger-kylin-security-changes.cfg b/plugin-kylin/conf/ranger-kylin-security-changes.cfg new file mode 100644 index 0000000..e6cc1f9 --- /dev/null +++ b/plugin-kylin/conf/ranger-kylin-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.kylin.service.name %REPOSITORY_NAME% mod create-if-not-exists + +ranger.plugin.kylin.policy.source.impl org.apache.ranger.admin.client.RangerAdminRESTClient mod create-if-not-exists + +ranger.plugin.kylin.policy.rest.url %POLICY_MGR_URL% mod create-if-not-exists +ranger.plugin.kylin.policy.rest.ssl.config.file /etc/hadoop/conf/ranger-policymgr-ssl.xml mod create-if-not-exists +ranger.plugin.kylin.policy.pollIntervalMs 30000 mod create-if-not-exists +ranger.plugin.kylin.policy.cache.dir %POLICY_CACHE_FILE_PATH% mod create-if-not-exists +ranger.plugin.kylin.policy.rest.client.connection.timeoutMs 120000 mod create-if-not-exists +ranger.plugin.kylin.policy.rest.client.read.timeoutMs 30000 mod create-if-not-exists \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/conf/ranger-kylin-security.xml ---------------------------------------------------------------------- diff --git a/plugin-kylin/conf/ranger-kylin-security.xml b/plugin-kylin/conf/ranger-kylin-security.xml new file mode 100644 index 0000000..7b383fc --- /dev/null +++ b/plugin-kylin/conf/ranger-kylin-security.xml @@ -0,0 +1,83 @@ +<?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>ranger.plugin.kylin.service.name</name> + <value>kylindev</value> + <description> + Name of the Ranger service containing policies for this kylin instance + </description> + </property> + + <property> + <name>ranger.plugin.kylin.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.kylin.policy.rest.url</name> + <value>http://policymanagerhost:port</value> + <description> + URL to Ranger Admin + </description> + </property> + + <property> + <name>ranger.plugin.kylin.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.kylin.policy.pollIntervalMs</name> + <value>30000</value> + <description> + How often to poll for changes in policies? + </description> + </property> + + <property> + <name>ranger.plugin.kylin.policy.cache.dir</name> + <value>/etc/ranger/hadoopdev/policycache</value> + <description> + Directory where Ranger policies are cached after successful retrieval from the source + </description> + </property> + + <property> + <name>ranger.plugin.kylin.policy.rest.client.connection.timeoutMs</name> + <value>120000</value> + <description> + RangerRestClient Connection Timeout in Milli Seconds + </description> + </property> + + <property> + <name>ranger.plugin.kylin.policy.rest.client.read.timeoutMs</name> + <value>30000</value> + <description> + RangerRestClient read Timeout in Milli Seconds + </description> + </property> +</configuration> http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/conf/ranger-policymgr-ssl-changes.cfg ---------------------------------------------------------------------- diff --git a/plugin-kylin/conf/ranger-policymgr-ssl-changes.cfg b/plugin-kylin/conf/ranger-policymgr-ssl-changes.cfg new file mode 100644 index 0000000..ae347e8 --- /dev/null +++ b/plugin-kylin/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 http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/conf/ranger-policymgr-ssl.xml ---------------------------------------------------------------------- diff --git a/plugin-kylin/conf/ranger-policymgr-ssl.xml b/plugin-kylin/conf/ranger-policymgr-ssl.xml new file mode 100644 index 0000000..1f9acf0 --- /dev/null +++ b/plugin-kylin/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>kylindev-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-kylindev-ssl.jceks</value> + <description> + java keystore credential file + </description> + </property> + <property> + <name>xasecure.policymgr.clientssl.truststore.credential.file</name> + <value>jceks://file/tmp/truststore-kylindev-ssl.jceks</value> + <description> + java truststore credential file + </description> + </property> +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/pom.xml ---------------------------------------------------------------------- diff --git a/plugin-kylin/pom.xml b/plugin-kylin/pom.xml new file mode 100644 index 0000000..bfce4c1 --- /dev/null +++ b/plugin-kylin/pom.xml @@ -0,0 +1,77 @@ +<?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-kylin-plugin</artifactId> + <name>Kylin Security Plugin</name> + <description>Kylin 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>1.1.0-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <dependencies> + <dependency> + <groupId>org.apache.kylin</groupId> + <artifactId>kylin-server-base</artifactId> + <version>${kylin.version}</version> + <scope>provided</scope> + <exclusions> + <exclusion> + <groupId>org.apache.kylin</groupId> + <artifactId>kylin-external-htrace</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.calcite</groupId> + <artifactId>calcite-core</artifactId> + </exclusion> + </exclusions> + </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> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>credentialbuilder</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.solr</groupId> + <artifactId>solr-solrj</artifactId> + <version>${solr.version}</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>${httpcomponents.httpcore.version}</version> + </dependency> + </dependencies> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/scripts/install.properties ---------------------------------------------------------------------- diff --git a/plugin-kylin/scripts/install.properties b/plugin-kylin/scripts/install.properties new file mode 100644 index 0000000..126eeba --- /dev/null +++ b/plugin-kylin/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=kylindev +# +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=../kylin + +# 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/kylin/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/kylin/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://[email protected]/ranger/audit +#XAAUDIT.HDFS.FILE_SPOOL_DIR=/var/log/kylin/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/kylin/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/kylin/audit +# XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=__REPLACE__LOG_DIR/kylin/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/kylin/audit +# XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=/var/log/kylin/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/kylin/audit +XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=__REPLACE__LOG_DIR/kylin/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=kylin + + +# +# Custom component group +# CUSTOM_COMPONENT_GROUP=<custom-group> +# keep blank if component group is default +CUSTOM_GROUP=hadoop http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java ---------------------------------------------------------------------- diff --git a/plugin-kylin/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java b/plugin-kylin/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java new file mode 100644 index 0000000..a745b87 --- /dev/null +++ b/plugin-kylin/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java @@ -0,0 +1,182 @@ +/* + * 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.kylin.authorizer; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Date; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.common.util.Pair; +import org.apache.kylin.metadata.project.ProjectInstance; +import org.apache.kylin.metadata.project.ProjectManager; +import org.apache.kylin.rest.security.AclEntityType; +import org.apache.kylin.rest.security.AclPermission; +import org.apache.kylin.rest.security.ExternalAclProvider; +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.service.RangerBasePlugin; +import org.apache.ranger.services.kylin.client.KylinResourceMgr; +import org.springframework.security.acls.model.Permission; + +import com.google.common.collect.Sets; + +public class RangerKylinAuthorizer extends ExternalAclProvider { + private static final Log LOG = LogFactory.getLog(RangerKylinAuthorizer.class); + + private static volatile RangerKylinPlugin kylinPlugin = null; + + private static String clientIPAddress = null; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerKylinAuthorizer.init()"); + } + + RangerKylinPlugin plugin = kylinPlugin; + + if (plugin == null) { + synchronized (RangerKylinAuthorizer.class) { + plugin = kylinPlugin; + + if (plugin == null) { + plugin = new RangerKylinPlugin(); + plugin.init(); + kylinPlugin = plugin; + + clientIPAddress = getClientIPAddress(); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerKylinAuthorizer.init()"); + } + } + + @Override + public boolean checkPermission(String user, List<String> groups, String entityType, String entityUuid, + Permission permission) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerKylinAuthorizer.checkPermission( user=" + user + ", groups=" + groups + + ", entityType=" + entityType + ", entityUuid=" + entityUuid + ", permission=" + permission + ")"); + } + + boolean ret = false; + + if (kylinPlugin != null) { + String projectName = null; + KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv(); + if (AclEntityType.PROJECT_INSTANCE.equals(entityType)) { + ProjectInstance projectInstance = ProjectManager.getInstance(kylinConfig).getPrjByUuid(entityUuid); + if (projectInstance != null) { + projectName = projectInstance.getName(); + } else { + if (LOG.isWarnEnabled()) { + LOG.warn("Could not find kylin project for given uuid=" + entityUuid); + } + } + } + + String accessType = ExternalAclProvider.transformPermission(permission); + String clusterName = kylinPlugin.getClusterName(); + RangerKylinAccessRequest request = new RangerKylinAccessRequest(projectName, user, groups, accessType, + clusterName, clientIPAddress); + + RangerAccessResult result = kylinPlugin.isAccessAllowed(request); + if (result != null && result.getIsAllowed()) { + ret = true; + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerKylinAuthorizer.checkPermission(): result=" + ret); + } + + return ret; + } + + private String getClientIPAddress() { + InetAddress ip = null; + try { + ip = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + if (LOG.isDebugEnabled()) { + LOG.debug("Failed to get client IP address." + e); + } + } + + String ret = null; + if (ip != null) { + ret = ip.getHostAddress(); + } + return ret; + } + + @Override + public List<Pair<String, AclPermission>> getAcl(String entityType, String entityUuid) { + // No need to implement + return null; + } +} + +class RangerKylinPlugin extends RangerBasePlugin { + public RangerKylinPlugin() { + super("kylin", "kylin"); + } + + @Override + public void init() { + super.init(); + + RangerDefaultAuditHandler auditHandler = new RangerDefaultAuditHandler(); + + super.setResultProcessor(auditHandler); + } +} + +class RangerKylinResource extends RangerAccessResourceImpl { + public RangerKylinResource(String projectName) { + if (StringUtils.isEmpty(projectName)) { + projectName = "*"; + } + + setValue(KylinResourceMgr.PROJECT, projectName); + } +} + +class RangerKylinAccessRequest extends RangerAccessRequestImpl { + public RangerKylinAccessRequest(String projectName, String user, List<String> groups, String accessType, + String clusterName, String clientIPAddress) { + super.setResource(new RangerKylinResource(projectName)); + super.setAccessType(accessType); + super.setUser(user); + super.setUserGroups(Sets.newHashSet(groups)); + super.setAccessTime(new Date()); + super.setClientIPAddress(clientIPAddress); + super.setAction(accessType); + super.setClusterName(clusterName); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/RangerServiceKylin.java ---------------------------------------------------------------------- diff --git a/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/RangerServiceKylin.java b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/RangerServiceKylin.java new file mode 100644 index 0000000..7dc7d74 --- /dev/null +++ b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/RangerServiceKylin.java @@ -0,0 +1,89 @@ +/* + * 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.kylin; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.service.RangerBaseService; +import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.apache.ranger.services.kylin.client.KylinResourceMgr; + +public class RangerServiceKylin extends RangerBaseService { + + private static final Log LOG = LogFactory.getLog(RangerServiceKylin.class); + + public RangerServiceKylin() { + super(); + } + + @Override + public void init(RangerServiceDef serviceDef, RangerService service) { + super.init(serviceDef, service); + } + + @Override + public Map<String, Object> validateConfig() throws Exception { + Map<String, Object> ret = new HashMap<String, Object>(); + String serviceName = getServiceName(); + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceKylin.validateConfig Service: (" + serviceName + " )"); + } + if (configs != null) { + try { + ret = KylinResourceMgr.validateConfig(serviceName, configs); + } catch (Exception e) { + LOG.error("<== RangerServiceKylin.validateConfig Error:" + e); + throw e; + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceKylin.validateConfig Response : (" + ret + " )"); + } + return ret; + } + + @Override + public List<String> lookupResource(ResourceLookupContext context) throws Exception { + + List<String> ret = new ArrayList<String>(); + String serviceName = getServiceName(); + Map<String, String> configs = getConfigs(); + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceKylin.lookupResource Context: (" + context + ")"); + } + if (context != null) { + try { + ret = KylinResourceMgr.getKylinResources(serviceName, configs, context); + } catch (Exception e) { + LOG.error("<==RangerServiceKylin.lookupResource Error : " + e); + throw e; + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceKylin.lookupResource Response: (" + ret + ")"); + } + return ret; + } +} http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinClient.java ---------------------------------------------------------------------- diff --git a/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinClient.java b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinClient.java new file mode 100644 index 0000000..9cf21aa --- /dev/null +++ b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinClient.java @@ -0,0 +1,282 @@ +/* + * 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.kylin.client; + +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.security.auth.Subject; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpStatus; +import org.apache.log4j.Logger; +import org.apache.ranger.plugin.client.BaseClient; +import org.apache.ranger.plugin.client.HadoopException; +import org.apache.ranger.plugin.util.PasswordUtils; +import org.apache.ranger.services.kylin.client.json.model.KylinProjectResponse; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; + +public class KylinClient extends BaseClient { + + private static final Logger LOG = Logger.getLogger(KylinClient.class); + + private static final String EXPECTED_MIME_TYPE = "application/json"; + + private static final String KYLIN_LIST_API_ENDPOINT = "/kylin/api/projects"; + + private static final String ERROR_MESSAGE = " 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 String kylinUrl; + private String userName; + private String password; + + public KylinClient(String serviceName, Map<String, String> configs) { + + super(serviceName, configs, "kylin-client"); + + this.kylinUrl = configs.get("kylin.url"); + this.userName = configs.get("username"); + this.password = configs.get("password"); + + if (StringUtils.isEmpty(this.kylinUrl)) { + LOG.error("No value found for configuration 'kylin.url'. Kylin resource lookup will fail."); + } + if (StringUtils.isEmpty(this.userName)) { + LOG.error("No value found for configuration 'username'. Kylin resource lookup will fail."); + } + if (StringUtils.isEmpty(this.password)) { + LOG.error("No value found for configuration 'password'. Kylin resource lookup will fail."); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Kylin client is build with url [" + this.kylinUrl + "], user: [" + this.userName + + "], password: [" + "*********" + "]."); + } + } + + public List<String> getProjectList(final String projectMatching, final List<String> existingProjects) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Getting kylin project list for projectMatching: " + projectMatching + ", existingProjects: " + + existingProjects); + } + Subject subj = getLoginSubject(); + if (subj == null) { + return Collections.emptyList(); + } + + List<String> ret = Subject.doAs(subj, new PrivilegedAction<List<String>>() { + + @Override + public List<String> run() { + + ClientResponse response = getClientResponse(kylinUrl, userName, password); + + List<KylinProjectResponse> projectResponses = getKylinProjectResponse(response); + + if (CollectionUtils.isEmpty(projectResponses)) { + return Collections.emptyList(); + } + + List<String> projects = getProjectFromResponse(projectMatching, existingProjects, projectResponses); + + return projects; + } + }); + + if (LOG.isDebugEnabled()) { + LOG.debug("Getting kylin project list result: " + ret); + } + return ret; + } + + private static ClientResponse getClientResponse(String kylinUrl, String userName, String password) { + ClientResponse response = null; + String[] kylinUrls = kylinUrl.trim().split("[,;]"); + if (ArrayUtils.isEmpty(kylinUrls)) { + return null; + } + + Client client = Client.create(); + String decryptedPwd = PasswordUtils.getDecryptPassword(password); + client.addFilter(new HTTPBasicAuthFilter(userName, decryptedPwd)); + + for (String currentUrl : kylinUrls) { + if (StringUtils.isBlank(currentUrl)) { + continue; + } + + String url = currentUrl.trim() + KYLIN_LIST_API_ENDPOINT; + try { + response = getProjectResponse(url, client); + + if (response != null) { + if (response.getStatus() == HttpStatus.SC_OK) { + break; + } else { + response.close(); + } + } + } catch (Throwable t) { + String msgDesc = "Exception while getting kylin response, kylinUrl: " + url; + LOG.error(msgDesc, t); + } + } + client.destroy(); + + return response; + } + + private List<KylinProjectResponse> getKylinProjectResponse(ClientResponse response) { + List<KylinProjectResponse> projectResponses = null; + try { + if (response != null && response.getStatus() == HttpStatus.SC_OK) { + String jsonString = response.getEntity(String.class); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + projectResponses = gson.fromJson(jsonString, new TypeToken<List<KylinProjectResponse>>() { + }.getType()); + } else { + String msgDesc = "Unable to get a valid response for " + "expected mime type : [" + EXPECTED_MIME_TYPE + + "], kylinUrl: " + kylinUrl + " - got null response."; + LOG.error(msgDesc); + HadoopException hdpException = new HadoopException(msgDesc); + hdpException.generateResponseDataMap(false, msgDesc, msgDesc + ERROR_MESSAGE, null, null); + throw hdpException; + } + } catch (HadoopException he) { + throw he; + } catch (Throwable t) { + String msgDesc = "Exception while getting kylin project response, kylinUrl: " + kylinUrl; + HadoopException hdpException = new HadoopException(msgDesc, t); + + LOG.error(msgDesc, t); + + hdpException.generateResponseDataMap(false, BaseClient.getMessage(t), msgDesc + ERROR_MESSAGE, null, null); + throw hdpException; + + } finally { + if (response != null) { + response.close(); + } + } + return projectResponses; + } + + private static ClientResponse getProjectResponse(String url, Client client) { + if (LOG.isDebugEnabled()) { + LOG.debug("getProjectResponse():calling " + url); + } + + WebResource webResource = client.resource(url); + + ClientResponse response = webResource.accept(EXPECTED_MIME_TYPE).get(ClientResponse.class); + + if (response != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("getProjectResponse():response.getStatus()= " + response.getStatus()); + } + if (response.getStatus() != HttpStatus.SC_OK) { + LOG.warn("getProjectResponse():response.getStatus()= " + response.getStatus() + " for URL " + url + + ", failed to get kylin project list."); + String jsonString = response.getEntity(String.class); + LOG.warn(jsonString); + } + } + return response; + } + + private static List<String> getProjectFromResponse(String projectMatching, List<String> existingProjects, + List<KylinProjectResponse> projectResponses) { + List<String> projcetNames = new ArrayList<String>(); + for (KylinProjectResponse project : projectResponses) { + String projectName = project.getName(); + if (CollectionUtils.isNotEmpty(existingProjects) && existingProjects.contains(projectName)) { + continue; + } + if (StringUtils.isEmpty(projectMatching) || projectMatching.startsWith("*") + || projectName.toLowerCase().startsWith(projectMatching.toLowerCase())) { + if (LOG.isDebugEnabled()) { + LOG.debug("getProjectFromResponse(): Adding kylin project " + projectName); + } + projcetNames.add(projectName); + } + } + return projcetNames; + } + + public static Map<String, Object> connectionTest(String serviceName, Map<String, String> configs) { + KylinClient kylinClient = getKylinClient(serviceName, configs); + List<String> strList = kylinClient.getProjectList(null, null); + + boolean connectivityStatus = false; + if (CollectionUtils.isNotEmpty(strList)) { + if (LOG.isDebugEnabled()) { + LOG.debug("ConnectionTest list size" + strList.size() + " kylin projects"); + } + connectivityStatus = true; + } + + Map<String, Object> responseData = new HashMap<String, Object>(); + if (connectivityStatus) { + String successMsg = "ConnectionTest Successful"; + BaseClient.generateResponseDataMap(connectivityStatus, successMsg, successMsg, null, null, responseData); + } else { + String failureMsg = "Unable to retrieve any kylin projects using given parameters."; + BaseClient.generateResponseDataMap(connectivityStatus, failureMsg, failureMsg + ERROR_MESSAGE, null, null, + responseData); + } + + return responseData; + } + + public static KylinClient getKylinClient(String serviceName, Map<String, String> configs) { + KylinClient kylinClient = null; + if (LOG.isDebugEnabled()) { + LOG.debug("Getting KylinClient for datasource: " + serviceName); + } + if (MapUtils.isEmpty(configs)) { + String msgDesc = "Could not connect kylin as connection configMap is empty."; + LOG.error(msgDesc); + HadoopException hdpException = new HadoopException(msgDesc); + hdpException.generateResponseDataMap(false, msgDesc, msgDesc + ERROR_MESSAGE, null, null); + throw hdpException; + } else { + kylinClient = new KylinClient(serviceName, configs); + } + return kylinClient; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinResourceMgr.java ---------------------------------------------------------------------- diff --git a/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinResourceMgr.java b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinResourceMgr.java new file mode 100644 index 0000000..ae96a20 --- /dev/null +++ b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/KylinResourceMgr.java @@ -0,0 +1,97 @@ +/* + * 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.kylin.client; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.ranger.plugin.service.ResourceLookupContext; + +public class KylinResourceMgr { + + public static final String PROJECT = "project"; + + private static final Logger LOG = Logger.getLogger(KylinResourceMgr.class); + + public static Map<String, Object> validateConfig(String serviceName, Map<String, String> configs) throws Exception { + Map<String, Object> ret = null; + + if (LOG.isDebugEnabled()) { + LOG.debug("==> KylinResourceMgr.validateConfig ServiceName: " + serviceName + "Configs" + configs); + } + + try { + ret = KylinClient.connectionTest(serviceName, configs); + } catch (Exception e) { + LOG.error("<== KylinResourceMgr.validateConfig Error: " + e); + throw e; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== KylinResourceMgr.validateConfig Result: " + ret); + } + return ret; + } + + public static List<String> getKylinResources(String serviceName, Map<String, String> configs, + ResourceLookupContext context) { + String userInput = context.getUserInput(); + String resource = context.getResourceName(); + Map<String, List<String>> resourceMap = context.getResources(); + if (LOG.isDebugEnabled()) { + LOG.debug("==> KylinResourceMgr.getKylinResources() userInput: " + userInput + ", resource: " + resource + + ", resourceMap: " + resourceMap); + } + + if (MapUtils.isEmpty(configs)) { + LOG.error("Connection Config is empty!"); + return null; + } + + if (StringUtils.isEmpty(userInput)) { + LOG.warn("User input is empty, set default value : *"); + userInput = "*"; + } + + List<String> projectList = null; + if (MapUtils.isNotEmpty(resourceMap)) { + projectList = resourceMap.get(PROJECT); + } + + final KylinClient kylinClient = KylinClient.getKylinClient(serviceName, configs); + if (kylinClient == null) { + LOG.error("Failed to getKylinClient!"); + return null; + } + + List<String> resultList = null; + + resultList = kylinClient.getProjectList(userInput, projectList); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== KylinResourceMgr.getKylinResources() result: " + resultList); + } + return resultList; + } + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/json/model/KylinProjectResponse.java ---------------------------------------------------------------------- diff --git a/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/json/model/KylinProjectResponse.java b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/json/model/KylinProjectResponse.java new file mode 100644 index 0000000..efed6bc --- /dev/null +++ b/plugin-kylin/src/main/java/org/apache/ranger/services/kylin/client/json/model/KylinProjectResponse.java @@ -0,0 +1,109 @@ +/* + * 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.kylin.client.json.model; + +import java.util.List; + +public class KylinProjectResponse { + private String uuid; + + private String version; + + private String name; + + private String owner; + + private String status; + + private String description; + + private List<String> tables; + + private List<String> models; + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List<String> getTables() { + return tables; + } + + public void setTables(List<String> tables) { + this.tables = tables; + } + + public List<String> getModels() { + return models; + } + + public void setModels(List<String> models) { + this.models = models; + } + + @Override + public String toString() { + return "KylinProjectResponse [uuid=" + uuid + ", version=" + version + ", name=" + name + ", owner=" + owner + + ", status=" + status + ", description=" + description + ", tables=" + tables + ", models=" + models + + "]"; + } +} http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index d6f98b4..1df5f2c 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,8 @@ <module>plugin-atlas</module> <module>plugin-sqoop</module> <module>ranger-sqoop-plugin-shim</module> + <module>plugin-kylin</module> + <module>ranger-kylin-plugin-shim</module> </modules> <properties> <maven.version.required>3.3.3</maven.version.required> @@ -183,6 +185,7 @@ <kafka.version>1.0.0</kafka.version> <kerby.version>1.0.0</kerby.version> <knox.gateway.version>1.0.0</knox.gateway.version> + <kylin.version>2.3.0</kylin.version> <libpam4j.version>1.8</libpam4j.version> <local.lib.dir>${project.basedir}/../lib/local</local.lib.dir> <log4j.version>1.2.17</log4j.version> @@ -420,6 +423,7 @@ <descriptor>src/main/assembly/ranger-src.xml</descriptor> <descriptor>src/main/assembly/plugin-atlas.xml</descriptor> <descriptor>src/main/assembly/plugin-sqoop.xml</descriptor> + <descriptor>src/main/assembly/plugin-kylin.xml</descriptor> </descriptors> </configuration> </plugin> http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/ranger-kylin-plugin-shim/.gitignore ---------------------------------------------------------------------- diff --git a/ranger-kylin-plugin-shim/.gitignore b/ranger-kylin-plugin-shim/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/ranger-kylin-plugin-shim/.gitignore @@ -0,0 +1 @@ +/target/ http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/ranger-kylin-plugin-shim/pom.xml ---------------------------------------------------------------------- diff --git a/ranger-kylin-plugin-shim/pom.xml b/ranger-kylin-plugin-shim/pom.xml new file mode 100644 index 0000000..fd040bb --- /dev/null +++ b/ranger-kylin-plugin-shim/pom.xml @@ -0,0 +1,72 @@ +<?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-kylin-plugin-shim</artifactId> + <name>Kylin Security Plugin Shim</name> + <description>Kylin 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>1.1.0-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <dependencies> + <dependency> + <groupId>org.apache.kylin</groupId> + <artifactId>kylin-server-base</artifactId> + <version>${kylin.version}</version> + <scope>provided</scope> + <exclusions> + <exclusion> + <groupId>org.apache.kylin</groupId> + <artifactId>kylin-external-htrace</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.calcite</groupId> + <artifactId>calcite-core</artifactId> + </exclusion> + </exclusions> + </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> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>credentialbuilder</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>ranger-plugin-classloader</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/ranger-kylin-plugin-shim/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java ---------------------------------------------------------------------- diff --git a/ranger-kylin-plugin-shim/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java b/ranger-kylin-plugin-shim/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java new file mode 100644 index 0000000..a12dfb1 --- /dev/null +++ b/ranger-kylin-plugin-shim/src/main/java/org/apache/ranger/authorization/kylin/authorizer/RangerKylinAuthorizer.java @@ -0,0 +1,121 @@ +/* + * 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.kylin.authorizer; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.kylin.common.util.Pair; +import org.apache.kylin.rest.security.AclPermission; +import org.apache.kylin.rest.security.ExternalAclProvider; +import org.apache.ranger.plugin.classloader.RangerPluginClassLoader; +import org.springframework.security.acls.model.Permission; + +public class RangerKylinAuthorizer extends ExternalAclProvider { + private static final Log LOG = LogFactory.getLog(RangerKylinAuthorizer.class); + + private static final String RANGER_PLUGIN_TYPE = "kylin"; + private static final String RANGER_KYLIN_AUTHORIZER_IMPL_CLASSNAME = "org.apache.ranger.authorization.kylin.authorizer.RangerKylinAuthorizer"; + + private ExternalAclProvider externalAclProvider = null; + private static RangerPluginClassLoader rangerPluginClassLoader = null; + + public RangerKylinAuthorizer() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerKylinAuthorizer.RangerKylinAuthorizer()"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerKylinAuthorizer.RangerKylinAuthorizer()"); + } + } + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerKylinAuthorizer.init()"); + } + + try { + + rangerPluginClassLoader = RangerPluginClassLoader.getInstance(RANGER_PLUGIN_TYPE, this.getClass()); + + @SuppressWarnings("unchecked") + Class<ExternalAclProvider> cls = (Class<ExternalAclProvider>) Class.forName( + RANGER_KYLIN_AUTHORIZER_IMPL_CLASSNAME, true, rangerPluginClassLoader); + + activatePluginClassLoader(); + + externalAclProvider = cls.newInstance(); + externalAclProvider.init(); + } catch (Exception e) { + LOG.error("Error Enabling RangerKylinPlugin", e); + } finally { + deactivatePluginClassLoader(); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerKylinAuthorizer.init()"); + } + } + + @Override + public boolean checkPermission(String user, List<String> groups, String entityType, String entityUuid, + Permission permission) { + boolean ret = false; + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerKylinAuthorizer.checkPermission()"); + } + + try { + activatePluginClassLoader(); + + ret = externalAclProvider.checkPermission(user, groups, entityType, entityUuid, permission); + } finally { + deactivatePluginClassLoader(); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerKylinAuthorizer.checkPermission()"); + } + + return ret; + } + + private void activatePluginClassLoader() { + if (rangerPluginClassLoader != null) { + rangerPluginClassLoader.activate(); + } + } + + private void deactivatePluginClassLoader() { + if (rangerPluginClassLoader != null) { + rangerPluginClassLoader.deactivate(); + } + } + + @Override + public List<Pair<String, AclPermission>> getAcl(String entityType, String entityUuid) { + // No need to implement + return null; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/2b1143ab/src/main/assembly/admin-web.xml ---------------------------------------------------------------------- diff --git a/src/main/assembly/admin-web.xml b/src/main/assembly/admin-web.xml index 29d728a..960c994 100644 --- a/src/main/assembly/admin-web.xml +++ b/src/main/assembly/admin-web.xml @@ -342,6 +342,19 @@ </includes> </moduleSet> + <moduleSet> + <binaries> + <includeDependencies>true</includeDependencies> + <outputDirectory>/ews/webapp/WEB-INF/classes/ranger-plugins/kylin</outputDirectory> + <unpack>false</unpack> + <directoryMode>755</directoryMode> + <fileMode>644</fileMode> + </binaries> + <includes> + <include>org.apache.ranger:ranger-kylin-plugin</include> + </includes> + </moduleSet> + </moduleSets> <fileSets>
