This is an automated email from the ASF dual-hosted git repository.

pengjianhua 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 39a53b6  RANGER-2170:Ranger supports plugin to enable, monitor and 
manage Elasticsearch
39a53b6 is described below

commit 39a53b6c448145c2a68839233281671f754e519b
Author: zhangqiang2 <[email protected]>
AuthorDate: Thu Dec 13 14:46:14 2018 +0800

    RANGER-2170:Ranger supports plugin to enable, monitor and manage 
Elasticsearch
    
    Signed-off-by: peng.jianhua <[email protected]>
---
 agents-common/scripts/enable-agent.sh              |  12 +-
 .../apache/ranger/plugin/client/BaseClient.java    |   2 +-
 .../plugin/store/EmbeddedServiceDefsUtil.java      |   8 +-
 .../ranger-servicedef-elasticsearch.json           | 196 ++++++++++++++
 plugin-elasticsearch/.gitignore                    |   1 +
 .../conf/ranger-elasticsearch-audit-changes.cfg    |  65 +++++
 .../conf/ranger-elasticsearch-audit.xml            | 271 ++++++++++++++++++++
 .../conf/ranger-elasticsearch-security-changes.cfg |  28 ++
 .../conf/ranger-elasticsearch-security.xml         |  83 ++++++
 .../conf/ranger-policymgr-ssl-changes.cfg          |  21 ++
 plugin-elasticsearch/conf/ranger-policymgr-ssl.xml |  49 ++++
 plugin-elasticsearch/pom.xml                       |  69 +++++
 plugin-elasticsearch/scripts/install.properties    | 140 ++++++++++
 .../authorizer/RangerElasticsearchAuthorizer.java  | 148 +++++++++++
 .../elasticsearch/RangerServiceElasticsearch.java  |  88 +++++++
 .../elasticsearch/client/ElasticsearchClient.java  | 282 +++++++++++++++++++++
 .../client/ElasticsearchResourceMgr.java           | 102 ++++++++
 .../elasticsearch/privilege/IndexPrivilege.java    |  55 ++++
 .../privilege/IndexPrivilegeUtils.java             | 102 ++++++++
 pom.xml                                            |  34 +++
 ranger-elasticsearch-plugin-shim/.gitignore        |   1 +
 .../conf/plugin-descriptor.properties              |  65 +++++
 .../conf/plugin-security.policy                    |  39 +++
 ranger-elasticsearch-plugin-shim/pom.xml           |  66 +++++
 .../RangerElasticsearchAccessControl.java          |  35 +++
 .../authorizer/RangerElasticsearchAuthorizer.java  | 119 +++++++++
 .../plugin/RangerElasticsearchPlugin.java          | 122 +++++++++
 .../action/filter/RangerSecurityActionFilter.java  |  82 ++++++
 .../plugin/authc/user/UsernamePasswordToken.java   | 103 ++++++++
 .../rest/filter/RangerSecurityRestFilter.java      |  73 ++++++
 .../elasticsearch/plugin/utils/RequestUtils.java   | 126 +++++++++
 src/main/assembly/admin-web.xml                    |  12 +
 src/main/assembly/plugin-elasticsearch.xml         | 197 ++++++++++++++
 33 files changed, 2793 insertions(+), 3 deletions(-)

diff --git a/agents-common/scripts/enable-agent.sh 
b/agents-common/scripts/enable-agent.sh
index ce0dc8c..b4194a7 100755
--- a/agents-common/scripts/enable-agent.sh
+++ b/agents-common/scripts/enable-agent.sh
@@ -210,6 +210,8 @@ 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
+elif [ "${HCOMPONENT_NAME}" = "elasticsearch" ]; then
+    HCOMPONENT_LIB_DIR=${HCOMPONENT_INSTALL_DIR}/plugins
 fi
 
 HCOMPONENT_CONF_DIR=${HCOMPONENT_INSTALL_DIR}/conf
@@ -219,7 +221,7 @@ if [ "${HCOMPONENT_NAME}" = "solr" ]; then
        install_owner=`ls -ld | cut -f 3 -d " "`
        echo "INFO: Creating $HCOMPONENT_CONF_DIR" 
        mkdir -p $HCOMPONENT_CONF_DIR
-       echo "INFO: Changing ownership of  $HCOMPONENT_CONF_DIR to 
$install_owner" 
+       echo "INFO: Changing ownership of $HCOMPONENT_CONF_DIR to 
$install_owner"
        chown $install_owner:$install_owner $HCOMPONENT_CONF_DIR
     fi    
 elif [ "${HCOMPONENT_NAME}" = "kafka" ]; then
@@ -230,6 +232,14 @@ elif [ "${HCOMPONENT_NAME}" = "yarn" ]; then
     HCOMPONENT_CONF_DIR=${HCOMPONENT_INSTALL_DIR}/etc/hadoop
 elif [ "${HCOMPONENT_NAME}" = "sqoop" ]; then
     HCOMPONENT_CONF_DIR=${HCOMPONENT_INSTALL_DIR}/conf
+elif [ "${HCOMPONENT_NAME}" = "elasticsearch" ]; then
+    
HCOMPONENT_CONF_DIR=${HCOMPONENT_INSTALL_DIR}/config/ranger-elasticsearch-plugin
+       if [ ! -d $HCOMPONENT_CONF_DIR ]; then
+       echo "INFO: Creating $HCOMPONENT_CONF_DIR"
+       mkdir -p $HCOMPONENT_CONF_DIR
+       echo "INFO: Changing ownership of $HCOMPONENT_CONF_DIR to 
$CFG_OWNER_INF"
+       chown $CFG_OWNER_INF $HCOMPONENT_CONF_DIR
+    fi
 fi
 
 HCOMPONENT_ARCHIVE_CONF_DIR=${HCOMPONENT_CONF_DIR}/.archive
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/client/BaseClient.java 
b/agents-common/src/main/java/org/apache/ranger/plugin/client/BaseClient.java
index e654f2b..ed002ef 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/client/BaseClient.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/client/BaseClient.java
@@ -37,7 +37,7 @@ public abstract class BaseClient {
 
 
        private static final String DEFAULT_NAME_RULE = "DEFAULT";
-       private static final String DEFAULT_ERROR_MESSAGE = " You can still 
save the repository and start creating "
+       protected static final String DEFAULT_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.";
 
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 118af1f..110f763 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,nifi-registry,sqoop,kylin";
+       private static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = 
"tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,nifi-registry,sqoop,kylin,elasticsearch";
        private static final String PROPERTY_SUPPORTED_SERVICE_DEFS = 
"ranger.supportedcomponents";
        private Set<String> supportedServiceDefs;
        public static final String EMBEDDED_SERVICEDEF_TAG_NAME  = "tag";
@@ -68,6 +68,7 @@ public class EmbeddedServiceDefsUtil {
        public static final String EMBEDDED_SERVICEDEF_SQOOP_NAME = "sqoop";
        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 PROPERTY_CREATE_EMBEDDED_SERVICE_DEFS = 
"ranger.service.store.create.embedded.service-defs";
 
@@ -102,6 +103,7 @@ public class EmbeddedServiceDefsUtil {
        private RangerServiceDef sqoopServiceDef;
        private RangerServiceDef kylinServiceDef;
        private RangerServiceDef abfsServiceDef;
+       private RangerServiceDef elasticsearchServiceDef;
 
        private RangerServiceDef tagServiceDef;
 
@@ -145,6 +147,7 @@ public class EmbeddedServiceDefsUtil {
                        sqoopServiceDef = getOrCreateServiceDef(store, 
EMBEDDED_SERVICEDEF_SQOOP_NAME);
                        kylinServiceDef = getOrCreateServiceDef(store, 
EMBEDDED_SERVICEDEF_KYLIN_NAME);
                        abfsServiceDef = getOrCreateServiceDef(store, 
EMBEDDED_SERVICEDEF_ABFS_NAME);
+                       elasticsearchServiceDef = getOrCreateServiceDef(store, 
EMBEDDED_SERVICEDEF_ELASTICSEARCH_NAME);
 
                        // Ensure that tag service def is updated with access 
types of all service defs
                        store.updateTagServiceDefForAccessTypes();
@@ -211,6 +214,9 @@ public class EmbeddedServiceDefsUtil {
                return getId(kylinServiceDef);
        }
 
+       public long getElasticsearchServiceDefId() {
+               return getId(elasticsearchServiceDef);
+       }
        public long getTagServiceDefId() { return getId(tagServiceDef); }
 
        public long getWasbServiceDefId() { return getId(wasbServiceDef); }
diff --git 
a/agents-common/src/main/resources/service-defs/ranger-servicedef-elasticsearch.json
 
b/agents-common/src/main/resources/service-defs/ranger-servicedef-elasticsearch.json
new file mode 100644
index 0000000..b055bf8
--- /dev/null
+++ 
b/agents-common/src/main/resources/service-defs/ranger-servicedef-elasticsearch.json
@@ -0,0 +1,196 @@
+{
+       "id":16,
+       "name": "elasticsearch",
+       "implClass": 
"org.apache.ranger.services.elasticsearch.RangerServiceElasticsearch",
+       "label": "ELASTICSEARCH",
+       "description": "ELASTICSEARCH",
+       "guid": "c0682ba7-7052-4c9c-a30e-84ccd5d98457",
+       "resources":
+       [
+               {
+                       "itemId": 1,
+                       "name": "index",
+                       "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": "Index",
+                       "description": "Elasticsearch Index"
+               }
+       ],
+
+       "accessTypes":
+       [
+               {
+                       "itemId": 1,
+                       "name": "all",
+                       "label": "all",
+                       "impliedGrants":
+                       [
+                               "monitor",
+                               "manage",
+                               "view_index_metadata",
+                               "read",
+                               "read_cross_cluster",
+                               "index",
+                               "create",
+                               "delete",
+                               "write",
+                               "delete_index",
+                               "create_index",
+                               "indices_put",
+                               "indices_search_shards",
+                               "indices_bulk",
+                               "indices_index"
+                       ]
+               },
+
+               {
+                       "itemId": 2,
+                       "name": "monitor",
+                       "label": "monitor"
+               },
+
+               {
+                       "itemId": 3,
+                       "name": "manage",
+                       "label": "manage",
+                       "impliedGrants":
+                       [
+                               "monitor"
+                       ]
+               },
+
+               {
+                       "itemId": 4,
+                       "name": "view_index_metadata",
+                       "label": "view_index_metadata",
+                       "impliedGrants":
+                       [
+                               "indices_search_shards"
+                       ]
+               },
+
+               {
+                       "itemId": 5,
+                       "name": "read",
+                       "label": "read"
+               },
+
+               {
+                       "itemId": 6,
+                       "name": "read_cross_cluster",
+                       "label": "read_cross_cluster",
+                       "impliedGrants":
+                       [
+                               "indices_search_shards"
+                       ]
+               },
+
+               {
+                       "itemId": 7,
+                       "name": "index",
+                       "label": "index",
+                       "impliedGrants":
+                       [
+                               "indices_put",
+                               "indices_bulk",
+                               "indices_index"
+                       ]
+               },
+
+               {
+                       "itemId": 8,
+                       "name": "create",
+                       "label": "create",
+                       "impliedGrants":
+                       [
+                               "indices_put",
+                               "indices_bulk",
+                               "indices_index"
+                       ]
+               },
+
+               {
+                       "itemId": 9,
+                       "name": "delete",
+                       "label": "delete",
+                       "impliedGrants":
+                       [
+                               "indices_bulk"
+                       ]
+               },
+
+               {
+                       "itemId": 10,
+                       "name": "write",
+                       "label": "write",
+                       "impliedGrants":
+                       [
+                               "indices_put"
+                       ]
+               },
+
+               {
+                       "itemId": 11,
+                       "name": "delete_index",
+                       "label": "delete_index"
+               },
+
+               {
+                       "itemId": 12,
+                       "name": "create_index",
+                       "label": "create_index"
+               }
+       ],
+
+       "configs":
+       [
+               {
+                       "itemId": 1,
+                       "name": "username",
+                       "type": "string",
+                       "mandatory": true,
+                       "validationRegEx":"",
+                       "validationMessage": "",
+                       "uiHint":"",
+                       "label": "Username"
+               },
+
+               {
+                       "itemId": 2,
+                       "name": "elasticsearch.url",
+                       "type": "string",
+                       "mandatory": true,
+                       "defaultValue": "",
+                       "validationRegEx":"",
+                       "validationMessage": "",
+                       "uiHint":"{\"TextFieldWithIcon\":true, \"info\": \"eg. 
'http://&lt;ipaddr&gt;:9200'\"}",
+                       "label": "Elasticsearch URL"
+               }
+       ],
+       "options": { "enableDenyAndExceptionsInPolicies": "false" },
+
+       "enums":
+       [
+
+       ],
+
+       "contextEnrichers":
+       [
+
+       ],
+
+       "policyConditions":
+       [
+
+       ]
+}
diff --git a/plugin-elasticsearch/.gitignore b/plugin-elasticsearch/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/plugin-elasticsearch/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/plugin-elasticsearch/conf/ranger-elasticsearch-audit-changes.cfg 
b/plugin-elasticsearch/conf/ranger-elasticsearch-audit-changes.cfg
new file mode 100644
index 0000000..8071e7b
--- /dev/null
+++ b/plugin-elasticsearch/conf/ranger-elasticsearch-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
diff --git a/plugin-elasticsearch/conf/ranger-elasticsearch-audit.xml 
b/plugin-elasticsearch/conf/ranger-elasticsearch-audit.xml
new file mode 100644
index 0000000..b9bdde5
--- /dev/null
+++ b/plugin-elasticsearch/conf/ranger-elasticsearch-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/elasticsearchdev/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/elasticsearch/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/elasticsearch/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>
diff --git 
a/plugin-elasticsearch/conf/ranger-elasticsearch-security-changes.cfg 
b/plugin-elasticsearch/conf/ranger-elasticsearch-security-changes.cfg
new file mode 100644
index 0000000..5b0deae
--- /dev/null
+++ b/plugin-elasticsearch/conf/ranger-elasticsearch-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.elasticsearch.service.name %REPOSITORY_NAME% mod 
create-if-not-exists
+
+ranger.plugin.elasticsearch.policy.source.impl 
org.apache.ranger.admin.client.RangerAdminRESTClient mod create-if-not-exists
+
+ranger.plugin.elasticsearch.policy.rest.url                %POLICY_MGR_URL%    
                      mod create-if-not-exists
+ranger.plugin.elasticsearch.policy.rest.ssl.config.file    
/etc/hadoop/conf/ranger-policymgr-ssl.xml mod create-if-not-exists
+ranger.plugin.elasticsearch.policy.pollIntervalMs          30000               
                      mod create-if-not-exists
+ranger.plugin.elasticsearch.policy.cache.dir               
%POLICY_CACHE_FILE_PATH%                  mod create-if-not-exists
+ranger.plugin.elasticsearch.policy.rest.client.connection.timeoutMs      
120000                                            mod create-if-not-exists
+ranger.plugin.elasticsearch.policy.rest.client.read.timeoutMs            30000 
                                        mod create-if-not-exists
\ No newline at end of file
diff --git a/plugin-elasticsearch/conf/ranger-elasticsearch-security.xml 
b/plugin-elasticsearch/conf/ranger-elasticsearch-security.xml
new file mode 100644
index 0000000..802e573
--- /dev/null
+++ b/plugin-elasticsearch/conf/ranger-elasticsearch-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.elasticsearch.service.name</name>
+               <value>elasticsearchdev</value>
+               <description>
+                       Name of the Ranger service containing policies for this 
elasticsearch instance
+               </description>
+       </property>
+
+       <property>
+               <name>ranger.plugin.elasticsearch.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.elasticsearch.policy.rest.url</name>
+               <value>http://policymanagerhost:port</value>
+               <description>
+                       URL to Ranger Admin
+               </description>
+       </property>
+
+       <property>
+               
<name>ranger.plugin.elasticsearch.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.elasticsearch.policy.pollIntervalMs</name>
+               <value>30000</value>
+               <description>
+                       How often to poll for changes in policies?
+               </description>
+       </property>
+
+       <property>
+               <name>ranger.plugin.elasticsearch.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.elasticsearch.policy.rest.client.connection.timeoutMs</name>
+               <value>120000</value>
+               <description>
+                       RangerRestClient Connection Timeout in Milli Seconds
+               </description>
+       </property>
+
+       <property>
+               
<name>ranger.plugin.elasticsearch.policy.rest.client.read.timeoutMs</name>
+               <value>30000</value>
+               <description>
+                       RangerRestClient read Timeout in Milli Seconds
+               </description>
+       </property>
+</configuration>
diff --git a/plugin-elasticsearch/conf/ranger-policymgr-ssl-changes.cfg 
b/plugin-elasticsearch/conf/ranger-policymgr-ssl-changes.cfg
new file mode 100644
index 0000000..ae347e8
--- /dev/null
+++ b/plugin-elasticsearch/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-elasticsearch/conf/ranger-policymgr-ssl.xml 
b/plugin-elasticsearch/conf/ranger-policymgr-ssl.xml
new file mode 100644
index 0000000..dcb0de0
--- /dev/null
+++ b/plugin-elasticsearch/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>elasticsearchdev-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-elasticsearchdev-ssl.jceks</value>
+               <description>
+                       java keystore credential file
+               </description>
+       </property>
+       <property>
+               
<name>xasecure.policymgr.clientssl.truststore.credential.file</name>
+               
<value>jceks://file/tmp/truststore-elasticsearchdev-ssl.jceks</value>
+               <description>
+                       java truststore credential file
+               </description>
+       </property>
+</configuration>
diff --git a/plugin-elasticsearch/pom.xml b/plugin-elasticsearch/pom.xml
new file mode 100644
index 0000000..b997310
--- /dev/null
+++ b/plugin-elasticsearch/pom.xml
@@ -0,0 +1,69 @@
+<?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-elasticsearch-plugin</artifactId>
+       <name>Elasticsearch Security Plugin</name>
+       <description>Elasticsearch 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>org.elasticsearch</groupId>
+                       <artifactId>elasticsearch</artifactId>
+                       <version>${elasticsearch.version}</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.ranger</groupId>
+                       
<artifactId>ranger-elasticsearch-plugin-shim</artifactId>
+                       <version>${project.version}</version>
+                       <scope>provided</scope>
+               </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.httpcomponents</groupId>
+                       <artifactId>httpcore</artifactId>
+                       <version>${httpcomponents.httpcore.version}</version>
+               </dependency>
+       </dependencies>
+</project>
diff --git a/plugin-elasticsearch/scripts/install.properties 
b/plugin-elasticsearch/scripts/install.properties
new file mode 100644
index 0000000..3a5b213
--- /dev/null
+++ b/plugin-elasticsearch/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=elasticsearchdev
+#
+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=../elasticsearch
+
+# 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/elasticsearch/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/elasticsearch/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/elasticsearch/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/elasticsearch/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/elasticsearch/audit
+#  
XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=__REPLACE__LOG_DIR/elasticsearch/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/elasticsearch/audit
+#  XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=/var/log/elasticsearch/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/elasticsearch/audit
+XAAUDIT.HDFS.LOCAL_ARCHIVE_DIRECTORY=__REPLACE__LOG_DIR/elasticsearch/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=elasticsearch
+
+
+#
+# Custom component group
+# CUSTOM_COMPONENT_GROUP=<custom-group>
+# keep blank if component group is default
+CUSTOM_GROUP=hadoop
diff --git 
a/plugin-elasticsearch/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAuthorizer.java
 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAuthorizer.java
new file mode 100644
index 0000000..a6b024f
--- /dev/null
+++ 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAuthorizer.java
@@ -0,0 +1,148 @@
+/*
+ * 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.elasticsearch.authorizer;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.logging.log4j.Logger;
+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.elasticsearch.client.ElasticsearchResourceMgr;
+import org.apache.ranger.services.elasticsearch.privilege.IndexPrivilegeUtils;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+
+import com.google.common.collect.Sets;
+
+public class RangerElasticsearchAuthorizer implements 
RangerElasticsearchAccessControl {
+
+       private static final Logger LOG = 
ESLoggerFactory.getLogger(RangerElasticsearchAuthorizer.class);
+
+       private static volatile RangerElasticsearchInnerPlugin 
elasticsearchPlugin = null;
+
+       public RangerElasticsearchAuthorizer() {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerElasticsearchAuthorizer.RangerElasticsearchAuthorizer()");
+               }
+
+               this.init();
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerElasticsearchAuthorizer.RangerElasticsearchAuthorizer()");
+               }
+       }
+
+       public void init() {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerElasticsearchAuthorizer.init()");
+               }
+
+               RangerElasticsearchInnerPlugin plugin = elasticsearchPlugin;
+
+               if (plugin == null) {
+                       synchronized (RangerElasticsearchAuthorizer.class) {
+                               plugin = elasticsearchPlugin;
+
+                               if (plugin == null) {
+                                       plugin = new 
RangerElasticsearchInnerPlugin();
+                                       plugin.init();
+                                       elasticsearchPlugin = plugin;
+                               }
+                       }
+               }
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerElasticsearchAuthorizer.init()");
+               }
+       }
+
+       @Override
+       public boolean checkPermission(String user, List<String> groups, String 
index, String action,
+                       String clientIPAddress) {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerElasticsearchAuthorizer.checkPermission( user=" + user + ", groups=" + 
groups
+                                       + ", index=" + index + ", action=" + 
action + ", clientIPAddress=" + clientIPAddress + ")");
+               }
+
+               boolean ret = false;
+
+               if (elasticsearchPlugin != null) {
+
+                       String privilege = 
IndexPrivilegeUtils.getPrivilegeFromAction(action);
+                       String clusterName = 
elasticsearchPlugin.getClusterName();
+                       RangerElasticsearchAccessRequest request = new 
RangerElasticsearchAccessRequest(user, groups, index,
+                                       privilege, clusterName, 
clientIPAddress);
+
+                       RangerAccessResult result = 
elasticsearchPlugin.isAccessAllowed(request);
+                       if (result != null && result.getIsAllowed()) {
+                               ret = true;
+                       }
+               }
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerElasticsearchAuthorizer.checkPermission(): result=" + ret);
+               }
+
+               return ret;
+       }
+}
+
+class RangerElasticsearchInnerPlugin extends RangerBasePlugin {
+       public RangerElasticsearchInnerPlugin() {
+               super("elasticsearch", "elasticsearch");
+       }
+
+       @Override
+       public void init() {
+               super.init();
+
+               RangerDefaultAuditHandler auditHandler = new 
RangerDefaultAuditHandler();
+
+               super.setResultProcessor(auditHandler);
+       }
+}
+
+class RangerElasticsearchResource extends RangerAccessResourceImpl {
+       public RangerElasticsearchResource(String index) {
+               if (StringUtils.isEmpty(index)) {
+                       index = "*";
+               }
+               setValue(ElasticsearchResourceMgr.INDEX, index);
+       }
+}
+
+class RangerElasticsearchAccessRequest extends RangerAccessRequestImpl {
+       public RangerElasticsearchAccessRequest(String user, List<String> 
groups, String index, String privilege,
+                       String clusterName, String clientIPAddress) {
+               super.setUser(user);
+               if (CollectionUtils.isNotEmpty(groups)) {
+                       super.setUserGroups(Sets.newHashSet(groups));
+               }
+               super.setResource(new RangerElasticsearchResource(index));
+               super.setAccessType(privilege);
+               super.setAction(privilege);
+               super.setClusterName(clusterName);
+               super.setClientIPAddress(clientIPAddress);
+               super.setAccessTime(new Date());
+       }
+}
diff --git 
a/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/RangerServiceElasticsearch.java
 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/RangerServiceElasticsearch.java
new file mode 100644
index 0000000..ed1c98e
--- /dev/null
+++ 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/RangerServiceElasticsearch.java
@@ -0,0 +1,88 @@
+/*
+ * 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.elasticsearch;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+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.elasticsearch.client.ElasticsearchResourceMgr;
+
+public class RangerServiceElasticsearch extends RangerBaseService {
+
+       private static final Logger LOG = 
Logger.getLogger(RangerServiceElasticsearch.class);
+
+       public RangerServiceElasticsearch() {
+               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("==> 
RangerServiceElasticsearch.validateConfig() service: " + serviceName);
+               }
+               if (configs != null) {
+                       try {
+                               ret = 
ElasticsearchResourceMgr.validateConfig(serviceName, configs);
+                       } catch (Exception e) {
+                               LOG.error("<== 
RangerServiceElasticsearch.validateConfig() error: " + e);
+                               throw e;
+                       }
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerServiceElasticsearch.validateConfig() result: " + 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("==> 
RangerServiceElasticsearch.lookupResource() context: " + context);
+               }
+               if (context != null) {
+                       try {
+                               ret = 
ElasticsearchResourceMgr.getElasticsearchResources(serviceName, configs, 
context);
+                       } catch (Exception e) {
+                               
LOG.error("<==RangerServiceElasticsearch.lookupResource() error: " + e);
+                               throw e;
+                       }
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerServiceElasticsearch.lookupResource() result: " + ret);
+               }
+               return ret;
+       }
+}
diff --git 
a/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/client/ElasticsearchClient.java
 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/client/ElasticsearchClient.java
new file mode 100644
index 0000000..d5c170d
--- /dev/null
+++ 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/client/ElasticsearchClient.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.elasticsearch.client;
+
+import java.lang.reflect.Type;
+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 java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.ws.rs.core.MediaType;
+
+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 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 ElasticsearchClient extends BaseClient {
+
+       private static final Logger LOG = 
Logger.getLogger(ElasticsearchClient.class);
+
+       private static final String ELASTICSEARCH_INDEX_API_ENDPOINT = "/_all";
+
+       private String elasticsearchUrl;
+
+       private String userName;
+
+       public ElasticsearchClient(String serviceName, Map<String, String> 
configs) {
+
+               super(serviceName, configs, "elasticsearch-client");
+               this.elasticsearchUrl = configs.get("elasticsearch.url");
+               this.userName = configs.get("username");
+
+               if (StringUtils.isEmpty(this.elasticsearchUrl)) {
+                       LOG.error("No value found for configuration 
'elasticsearch.url'. Elasticsearch resource lookup will fail.");
+               }
+
+               if (StringUtils.isEmpty(this.userName)) {
+                       LOG.error("No value found for configuration 'username'. 
Elasticsearch resource lookup will fail.");
+               }
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("Elasticsearch client is build with url: [" + 
this.elasticsearchUrl + "], user: [" + this.userName
+                                       + "].");
+               }
+       }
+
+       public List<String> getIndexList(final String indexMatching, final 
List<String> existingIndices) {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("Get elasticsearch index list for 
indexMatching: " + indexMatching + ", existingIndices: "
+                                       + existingIndices);
+               }
+               Subject subj = getLoginSubject();
+               if (subj == null) {
+                       return Collections.emptyList();
+               }
+
+               List<String> ret = Subject.doAs(subj, new 
PrivilegedAction<List<String>>() {
+
+                       @Override
+                       public List<String> run() {
+
+                               String indexApi = null;
+                               if (StringUtils.isNotEmpty(indexMatching)) {
+                                       indexApi = '/' + indexMatching;
+                                       if (!indexApi.endsWith("*")) {
+                                               indexApi += "*";
+                                       }
+                               } else {
+                                       indexApi = 
ELASTICSEARCH_INDEX_API_ENDPOINT;
+                               }
+                               ClientResponse response = 
getClientResponse(elasticsearchUrl, indexApi, userName);
+
+                               Map<String, Object> index2detailMap = 
getElasticsearchResourceResponse(response,
+                                               new TypeToken<HashMap<String, 
Object>>() {
+                                               }.getType());
+                               if (MapUtils.isEmpty(index2detailMap)) {
+                                       return Collections.emptyList();
+                               }
+
+                               Set<String> indexResponses = 
index2detailMap.keySet();
+                               if (CollectionUtils.isEmpty(indexResponses)) {
+                                       return Collections.emptyList();
+                               }
+
+                               return 
filterResourceFromResponse(indexMatching, existingIndices, new 
ArrayList<>(indexResponses));
+                       }
+               });
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("Get elasticsearch index list result: " + 
ret);
+               }
+               return ret;
+       }
+
+       private static ClientResponse getClientResponse(String 
elasticsearchUrl, String elasticsearchApi, String userName) {
+               String[] elasticsearchUrls = 
elasticsearchUrl.trim().split("[,;]");
+               if (ArrayUtils.isEmpty(elasticsearchUrls)) {
+                       return null;
+               }
+
+               ClientResponse response = null;
+               Client client = Client.create();
+               client.addFilter(new HTTPBasicAuthFilter(userName, 
StringUtils.EMPTY));
+               for (String currentUrl : elasticsearchUrls) {
+                       if (StringUtils.isBlank(currentUrl)) {
+                               continue;
+                       }
+
+                       String url = currentUrl.trim() + elasticsearchApi;
+                       try {
+                               response = getClientResponse(url, client);
+
+                               if (response != null) {
+                                       if (response.getStatus() == 
HttpStatus.SC_OK) {
+                                               break;
+                                       } else {
+                                               response.close();
+                                       }
+                               }
+                       } catch (Throwable t) {
+                               String msgDesc = "Exception while getting 
elasticsearch response, elasticsearchUrl: " + url;
+                               LOG.error(msgDesc, t);
+                       }
+               }
+               client.destroy();
+
+               return response;
+       }
+
+       private static ClientResponse getClientResponse(String url, Client 
client) {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("getClientResponse():calling " + url);
+               }
+
+               WebResource webResource = client.resource(url);
+
+               ClientResponse response = 
webResource.accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+               if (response != null) {
+                       if (LOG.isDebugEnabled()) {
+                               
LOG.debug("getClientResponse():response.getStatus()= " + response.getStatus());
+                       }
+                       if (response.getStatus() != HttpStatus.SC_OK) {
+                               
LOG.warn("getClientResponse():response.getStatus()= " + response.getStatus() + 
" for URL " + url
+                                               + ", failed to get 
elasticsearch resource list, response= " + response.getEntity(String.class));
+                       }
+               }
+               return response;
+       }
+
+       private <T> T getElasticsearchResourceResponse(ClientResponse response, 
Type type) {
+               T resource = null;
+               try {
+                       if (response != null && response.getStatus() == 
HttpStatus.SC_OK) {
+                               String jsonString = 
response.getEntity(String.class);
+                               Gson gson = new 
GsonBuilder().setPrettyPrinting().create();
+
+                               resource = gson.fromJson(jsonString, type);
+                       } else {
+                               String msgDesc = "Unable to get a valid 
response for " + "expected mime type : ["
+                                               + MediaType.APPLICATION_JSON + 
"], elasticsearchUrl: " + elasticsearchUrl
+                                               + " - got null response.";
+                               LOG.error(msgDesc);
+                               HadoopException hdpException = new 
HadoopException(msgDesc);
+                               hdpException.generateResponseDataMap(false, 
msgDesc, msgDesc + DEFAULT_ERROR_MESSAGE, null, null);
+                               throw hdpException;
+                       }
+               } catch (HadoopException he) {
+                       throw he;
+               } catch (Throwable t) {
+                       String msgDesc = "Exception while getting elasticsearch 
resource response, elasticsearchUrl: "
+                                       + elasticsearchUrl;
+                       HadoopException hdpException = new 
HadoopException(msgDesc, t);
+
+                       LOG.error(msgDesc, t);
+
+                       hdpException.generateResponseDataMap(false, 
BaseClient.getMessage(t), msgDesc + DEFAULT_ERROR_MESSAGE, null,
+                                       null);
+                       throw hdpException;
+
+               } finally {
+                       if (response != null) {
+                               response.close();
+                       }
+               }
+               return resource;
+       }
+
+       private static List<String> filterResourceFromResponse(String 
resourceMatching, List<String> existingResources,
+                       List<String> resourceResponses) {
+               List<String> resources = new ArrayList<String>();
+               for (String resourceResponse : resourceResponses) {
+                       if (CollectionUtils.isNotEmpty(existingResources) && 
existingResources.contains(resourceResponse)) {
+                               continue;
+                       }
+                       if (StringUtils.isEmpty(resourceMatching) || 
resourceMatching.startsWith("*")
+                                       || 
resourceResponse.toLowerCase().startsWith(resourceMatching.toLowerCase())) {
+                               if (LOG.isDebugEnabled()) {
+                                       
LOG.debug("filterResourceFromResponse(): Adding elasticsearch resource " + 
resourceResponse);
+                               }
+                               resources.add(resourceResponse);
+                       }
+               }
+               return resources;
+       }
+
+       public static Map<String, Object> connectionTest(String serviceName, 
Map<String, String> configs) {
+               ElasticsearchClient elasticsearchClient = 
getElasticsearchClient(serviceName, configs);
+               List<String> indexList = elasticsearchClient.getIndexList(null, 
null);
+
+               boolean connectivityStatus = false;
+               if (CollectionUtils.isNotEmpty(indexList)) {
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("ConnectionTest list size " + 
indexList.size() + " elasticsearch indices.");
+                       }
+                       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 
elasticsearch indices using given parameters.";
+                       BaseClient.generateResponseDataMap(connectivityStatus, 
failureMsg, failureMsg + DEFAULT_ERROR_MESSAGE, null,
+                                       null, responseData);
+               }
+
+               return responseData;
+       }
+
+       public static ElasticsearchClient getElasticsearchClient(String 
serviceName, Map<String, String> configs) {
+               ElasticsearchClient elasticsearchClient = null;
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("Getting elasticsearchClient for datasource: 
" + serviceName);
+               }
+               if (MapUtils.isEmpty(configs)) {
+                       String msgDesc = "Could not connect elasticsearch as 
connection configMap is empty.";
+                       LOG.error(msgDesc);
+                       HadoopException hdpException = new 
HadoopException(msgDesc);
+                       hdpException.generateResponseDataMap(false, msgDesc, 
msgDesc + DEFAULT_ERROR_MESSAGE, null, null);
+                       throw hdpException;
+               } else {
+                       elasticsearchClient = new 
ElasticsearchClient(serviceName, configs);
+               }
+               return elasticsearchClient;
+       }
+}
diff --git 
a/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/client/ElasticsearchResourceMgr.java
 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/client/ElasticsearchResourceMgr.java
new file mode 100644
index 0000000..d7980aa
--- /dev/null
+++ 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/client/ElasticsearchResourceMgr.java
@@ -0,0 +1,102 @@
+/*
+ * 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.elasticsearch.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 ElasticsearchResourceMgr {
+
+       public static final String INDEX = "index";
+
+       private static final Logger LOG = 
Logger.getLogger(ElasticsearchResourceMgr.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("==> 
ElasticsearchResourceMgr.validateConfig() serviceName: " + serviceName + ", 
configs: "
+                                       + configs);
+               }
+
+               try {
+                       ret = ElasticsearchClient.connectionTest(serviceName, 
configs);
+               } catch (Exception e) {
+                       LOG.error("<== 
ElasticsearchResourceMgr.validateConfig() error: " + e);
+                       throw e;
+               }
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
ElasticsearchResourceMgr.validateConfig() result: " + ret);
+               }
+               return ret;
+       }
+
+       public static List<String> getElasticsearchResources(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("==> 
ElasticsearchResourceMgr.getElasticsearchResources()  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 = "*";
+               }
+
+               final ElasticsearchClient elasticsearchClient = 
ElasticsearchClient.getElasticsearchClient(serviceName, configs);
+               if (elasticsearchClient == null) {
+                       LOG.error("Failed to getElasticsearchResources!");
+                       return null;
+               }
+
+               List<String> resultList = null;
+
+               if (StringUtils.isNotEmpty(resource)) {
+                       switch (resource) {
+                       case INDEX:
+                               List<String> existingConnectors = 
resourceMap.get(INDEX);
+                               resultList = 
elasticsearchClient.getIndexList(userInput, existingConnectors);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
ElasticsearchResourceMgr.getElasticsearchResources() result: " + resultList);
+               }
+               return resultList;
+       }
+
+}
diff --git 
a/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/privilege/IndexPrivilege.java
 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/privilege/IndexPrivilege.java
new file mode 100644
index 0000000..4691a51
--- /dev/null
+++ 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/privilege/IndexPrivilege.java
@@ -0,0 +1,55 @@
+/*
+ * 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.elasticsearch.privilege;
+
+import java.util.List;
+
+public class IndexPrivilege {
+
+       private String privilege;
+
+       private List<String> actions;
+
+       public IndexPrivilege(String privilege, List<String> actions) {
+               super();
+               this.privilege = privilege;
+               this.actions = actions;
+       }
+
+       public String getPrivilege() {
+               return privilege;
+       }
+
+       public void setPrivilege(String privilege) {
+               this.privilege = privilege;
+       }
+
+       public List<String> getActions() {
+               return actions;
+       }
+
+       public void setActions(List<String> actions) {
+               this.actions = actions;
+       }
+
+       @Override
+       public String toString() {
+               return "IndexPrivilege [privilege=" + privilege + ", actions=" 
+ actions + "]";
+       }
+
+}
\ No newline at end of file
diff --git 
a/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/privilege/IndexPrivilegeUtils.java
 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/privilege/IndexPrivilegeUtils.java
new file mode 100644
index 0000000..16e666a
--- /dev/null
+++ 
b/plugin-elasticsearch/src/main/java/org/apache/ranger/services/elasticsearch/privilege/IndexPrivilegeUtils.java
@@ -0,0 +1,102 @@
+/*
+ * 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.elasticsearch.privilege;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+
+public class IndexPrivilegeUtils {
+       // These privileges have priority, should be matched in order
+       private static final List<IndexPrivilege> privileges = new 
LinkedList<>();
+
+       // External Privileges for users
+       public static final String ALL = "all";
+       public static final String MONITOR = "monitor";
+       public static final String MANAGE = "manage";
+       public static final String VIEW_INDEX_METADATA = "view_index_metadata";
+       public static final String READ = "read";
+       public static final String READ_CROSS_CLUSTER = "read_cross_cluster";
+       public static final String INDEX = "index";
+       public static final String CREATE = "create";
+       public static final String DELETE = "delete";
+       public static final String WRITE = "write";
+       public static final String DELETE_INDEX = "delete_index";
+       public static final String CREATE_INDEX = "create_index";
+
+       // Internal Privileges for Ranger authentication
+       public static final String INDICES_PUT = "indices_put";
+       public static final String INDICES_SEARCH_SHARDS = 
"indices_search_shards";
+       public static final String INDICES_BULK = "indices_bulk";
+       public static final String INDICES_INDEX = "indices_index";
+
+       static {
+               // First Priority
+               privileges.add(new IndexPrivilege(VIEW_INDEX_METADATA,
+                               Arrays.asList("indices:admin/aliases/get", 
"indices:admin/aliases/exists", "indices:admin/get",
+                                               "indices:admin/exists", 
"indices:admin/mappings/fields/get", "indices:admin/mappings/get",
+                                               "indices:admin/types/exists", 
"indices:admin/validate/query", "indices:monitor/settings/get")));
+               privileges.add(new IndexPrivilege(READ, 
Arrays.asList("indices:data/read/")));
+               privileges.add(
+                               new IndexPrivilege(READ_CROSS_CLUSTER, 
Arrays.asList("internal:transport/proxy/indices:data/read/")));
+               privileges.add(new IndexPrivilege(INDEX, 
Arrays.asList("indices:data/write/update")));
+
+               privileges.add(new IndexPrivilege(DELETE, 
Arrays.asList("indices:data/write/delete")));
+               privileges.add(new IndexPrivilege(DELETE_INDEX, 
Arrays.asList("indices:admin/delete")));
+               privileges.add(new IndexPrivilege(CREATE_INDEX, 
Arrays.asList("indices:admin/create")));
+
+               privileges.add(new IndexPrivilege(INDICES_PUT, 
Arrays.asList("indices:admin/mapping/put")));
+               privileges.add(new IndexPrivilege(INDICES_SEARCH_SHARDS, 
Arrays.asList("indices:admin/shards/search_shards")));
+               privileges.add(new IndexPrivilege(INDICES_BULK, 
Arrays.asList("indices:data/write/bulk")));
+               privileges.add(new IndexPrivilege(INDICES_INDEX, 
Arrays.asList("indices:data/write/index")));
+
+               // Second Priority
+               privileges.add(new IndexPrivilege(MONITOR, 
Arrays.asList("indices:monitor/")));
+               privileges.add(new IndexPrivilege(MANAGE, 
Arrays.asList("indices:admin/")));
+               privileges.add(new IndexPrivilege(WRITE, 
Arrays.asList("indices:data/write/")));
+
+               // Last Priority
+               privileges.add(
+                               new IndexPrivilege(ALL, 
Arrays.asList("indices:", "internal:transport/proxy/indices:", "cluster:")));
+
+       }
+
+       /**
+        * If action is empty or not matched, set default privilege "all".
+        * @param action
+        * @return privilege
+        */
+       public static String getPrivilegeFromAction(String action) {
+               if (StringUtils.isEmpty(action)) {
+                       return ALL;
+               }
+
+               for (IndexPrivilege privilege : privileges) {
+                       // Get the privilege of matched action rule in order
+                       for (String actionRule : privilege.getActions()) {
+                               if (action.startsWith(actionRule)) {
+                                       return privilege.getPrivilege();
+                               }
+                       }
+               }
+
+               return ALL;
+       }
+}
diff --git a/pom.xml b/pom.xml
index a11cf51..2a2540a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -107,6 +107,7 @@
         <curator.test.version>2.12.0</curator.test.version>
         <derby.version>10.11.1.1</derby.version>
         <eclipse.jpa.version>2.5.2</eclipse.jpa.version>
+        <elasticsearch.version>6.2.2</elasticsearch.version>
         <findbugs.plugin.version>3.0.3</findbugs.plugin.version>
         <google.guava.version>25.1-jre</google.guava.version>
         <googlecode.log4jdbc.version>1.2</googlecode.log4jdbc.version>
@@ -221,6 +222,8 @@
                 <module>ranger-sqoop-plugin-shim</module>
                 <module>plugin-kylin</module>
                 <module>ranger-kylin-plugin-shim</module>
+                <module>plugin-elasticsearch</module>
+                <module>ranger-elasticsearch-plugin-shim</module>
             </modules>
             <build>
                 <plugins>
@@ -247,6 +250,7 @@
                                 
<descriptor>src/main/assembly/plugin-atlas.xml</descriptor>
                                 
<descriptor>src/main/assembly/plugin-sqoop.xml</descriptor>
                                 
<descriptor>src/main/assembly/plugin-kylin.xml</descriptor>
+                                
<descriptor>src/main/assembly/plugin-elasticsearch.xml</descriptor>
                             </descriptors>
                         </configuration>
                     </plugin>
@@ -578,6 +582,33 @@
             </build>
         </profile>
         <profile>
+            <id>ranger-elasticsearch-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-elasticsearch</module>
+                <module>ranger-elasticsearch-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-elasticsearch.xml</descriptor>
+                            </descriptors>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
             <id>linux</id>
             <activation>
                 <os>
@@ -629,6 +660,8 @@
                 <module>ranger-sqoop-plugin-shim</module>
                 <module>plugin-kylin</module>
                 <module>ranger-kylin-plugin-shim</module>
+                <module>plugin-elasticsearch</module>
+                <module>ranger-elasticsearch-plugin-shim</module>
                 <module>unixauthnative</module>
             </modules>
             <build>
@@ -656,6 +689,7 @@
                                 
<descriptor>src/main/assembly/plugin-atlas.xml</descriptor>
                                 
<descriptor>src/main/assembly/plugin-sqoop.xml</descriptor>
                                 
<descriptor>src/main/assembly/plugin-kylin.xml</descriptor>
+                                
<descriptor>src/main/assembly/plugin-elasticsearch.xml</descriptor>
                             </descriptors>
                         </configuration>
                     </plugin>
diff --git a/ranger-elasticsearch-plugin-shim/.gitignore 
b/ranger-elasticsearch-plugin-shim/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/ranger-elasticsearch-plugin-shim/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/ranger-elasticsearch-plugin-shim/conf/plugin-descriptor.properties 
b/ranger-elasticsearch-plugin-shim/conf/plugin-descriptor.properties
new file mode 100644
index 0000000..95f9604
--- /dev/null
+++ b/ranger-elasticsearch-plugin-shim/conf/plugin-descriptor.properties
@@ -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.
+
+# Elasticsearch plugin descriptor file
+# This file must exist as 'plugin-descriptor.properties' in a folder named 
`elasticsearch`
+# inside all plugins.
+#
+### example plugin for "foo"
+#
+# foo.zip <-- zip file for the plugin, with this structure:
+#|____elasticsearch/
+#| |____   <arbitrary name1>.jar <-- classes, resources, dependencies
+#| |____   <arbitrary nameN>.jar <-- any number of jars
+#| |____   plugin-descriptor.properties <-- example contents below:
+#
+# classname=foo.bar.BazPlugin
+# description=My cool plugin
+# version=2.0
+# elasticsearch.version=2.0
+# java.version=1.7
+#
+### mandatory elements for all plugins:
+#
+# 'description': simple summary of the plugin
+description=Elasticsearch Security Plugin
+#
+# 'version': plugin's version
+version=${project.version}
+#
+# 'name': the plugin name
+name=ranger-elasticsearch-plugin
+#
+# 'classname': the name of the class to load, fully-qualified.
+classname=org.apache.ranger.authorization.elasticsearch.plugin.RangerElasticsearchPlugin
+#
+# 'java.version': version of java the code is built against
+# use the system property java.specification.version
+# version string must be a sequence of nonnegative decimal integers
+# separated by "."'s and may have leading zeros
+java.version=${javac.target.version}
+#
+# 'elasticsearch.version': version of elasticsearch compiled against
+elasticsearch.version=${elasticsearch.version}
+### optional elements for plugins:
+#
+#  'extended.plugins': other plugins this plugin extends through SPI
+#extended.plugins=${extendedPlugins}
+#
+# 'has.native.controller': whether or not the plugin has a native controller
+has.native.controller=false
+#
+# 'requires.keystore': whether or not the plugin needs the elasticsearch 
keystore be created
+requires.keystore=false
diff --git a/ranger-elasticsearch-plugin-shim/conf/plugin-security.policy 
b/ranger-elasticsearch-plugin-shim/conf/plugin-security.policy
new file mode 100644
index 0000000..4f96d87
--- /dev/null
+++ b/ranger-elasticsearch-plugin-shim/conf/plugin-security.policy
@@ -0,0 +1,39 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.
+ */
+
+grant {
+  permission java.lang.RuntimePermission "createClassLoader";
+  permission java.lang.RuntimePermission "getClassLoader";
+  permission java.lang.RuntimePermission "setContextClassLoader";
+  permission java.lang.RuntimePermission "shutdownHooks";
+  permission java.lang.RuntimePermission "accessDeclaredMembers";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+  permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+
+  permission javax.security.auth.AuthPermission "getLoginConfiguration";
+  permission javax.security.auth.AuthPermission "setLoginConfiguration";
+
+  permission java.net.NetPermission "getProxySelector";
+  // adapt to connect different IP and Port
+  permission java.net.SocketPermission "*", "connect,resolve";
+
+  permission java.util.PropertyPermission "*", "read,write";
+  // adapt to different directories configured by user
+  permission java.io.FilePermission "<<ALL FILES>>", "read,write";
+};
diff --git a/ranger-elasticsearch-plugin-shim/pom.xml 
b/ranger-elasticsearch-plugin-shim/pom.xml
new file mode 100644
index 0000000..59a653b
--- /dev/null
+++ b/ranger-elasticsearch-plugin-shim/pom.xml
@@ -0,0 +1,66 @@
+<?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-elasticsearch-plugin-shim</artifactId>
+       <name>Elasticsearch Security Plugin Shim</name>
+       <description>Elasticsearch 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.elasticsearch</groupId>
+                       <artifactId>elasticsearch</artifactId>
+                       <version>${elasticsearch.version}</version>
+                       <scope>provided</scope>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.apache.ranger</groupId>
+                       <artifactId>ranger-plugin-classloader</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>commons-collections</groupId>
+                       <artifactId>commons-collections</artifactId>
+                       <version>${commons.collections.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>commons-lang</groupId>
+                       <artifactId>commons-lang</artifactId>
+                       <version>${commons.lang.version}</version>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-log4j12</artifactId>
+                       <version>${slf4j-api.version}</version>
+                       <scope>runtime</scope>
+               </dependency>
+       </dependencies>
+</project>
\ No newline at end of file
diff --git 
a/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAccessControl.java
 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAccessControl.java
new file mode 100644
index 0000000..f9996b0
--- /dev/null
+++ 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAccessControl.java
@@ -0,0 +1,35 @@
+/*
+ * 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.elasticsearch.authorizer;
+
+import java.util.List;
+
+public interface RangerElasticsearchAccessControl {
+
+       /**
+        * Check permission for user do action on the elasticsearch index.
+        *
+        * @param user The user do the request.
+        * @param groups The groups of the user.
+        * @param index The elasticsearch index.
+        * @param action The operation type.
+        * @param clientIPAddress The clent IP address.
+        * @return Check permission result.
+        */
+       boolean checkPermission(String user, List<String> groups, String index, 
String action, String clientIPAddress);
+}
diff --git 
a/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAuthorizer.java
 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAuthorizer.java
new file mode 100644
index 0000000..8f33cb9
--- /dev/null
+++ 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/authorizer/RangerElasticsearchAuthorizer.java
@@ -0,0 +1,119 @@
+/*
+ * 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.elasticsearch.authorizer;
+
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.ranger.plugin.classloader.RangerPluginClassLoader;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+
+public class RangerElasticsearchAuthorizer {
+
+       private static final Logger LOG = 
ESLoggerFactory.getLogger(RangerElasticsearchAuthorizer.class);
+
+       private static final String RANGER_PLUGIN_TYPE = "elasticsearch";
+
+       private static final String 
RANGER_ELASTICSEARCH_AUTHORIZER_IMPL_CLASSNAME = 
"org.apache.ranger.authorization.elasticsearch.authorizer.RangerElasticsearchAuthorizer";
+
+       private static RangerPluginClassLoader rangerPluginClassLoader = null;
+
+       private static ClassLoader esClassLoader = null;
+
+       private RangerElasticsearchAccessControl 
rangerElasticsearchAccessControl = null;
+
+       public RangerElasticsearchAuthorizer() {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerElasticsearchAuthorizer.RangerElasticsearchAuthorizer()");
+               }
+
+               this.init();
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerElasticsearchAuthorizer.RangerElasticsearchAuthorizer()");
+               }
+       }
+
+       public void init() {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> RangerElasticsearchAuthorizer.init()");
+               }
+
+               try {
+
+                       // In elasticsearch this.getClass().getClassLoader() is 
FactoryURLClassLoader,
+                       // but Thread.currentThread().getContextClassLoader() 
is AppClassLoader.
+                       esClassLoader = 
Thread.currentThread().getContextClassLoader();
+                       
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+
+                       rangerPluginClassLoader = 
RangerPluginClassLoader.getInstance(RANGER_PLUGIN_TYPE, this.getClass());
+                       
Thread.currentThread().setContextClassLoader(esClassLoader);
+
+                       @SuppressWarnings("unchecked")
+                       Class<RangerElasticsearchAccessControl> cls = 
(Class<RangerElasticsearchAccessControl>) Class
+                                       
.forName(RANGER_ELASTICSEARCH_AUTHORIZER_IMPL_CLASSNAME, true, 
rangerPluginClassLoader);
+
+                       activatePluginClassLoader();
+
+                       rangerElasticsearchAccessControl = cls.newInstance();
+               } catch (Exception e) {
+                       LOG.error("Error Enabling 
RangerElasticsearchAuthorizer", e);
+               } finally {
+                       deactivatePluginClassLoader();
+               }
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== RangerElasticsearchAuthorizer.init()");
+               }
+       }
+
+       public boolean checkPermission(String user, List<String> groups, String 
index, String action,
+                       String clientIPAddress) {
+               boolean ret = false;
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerElasticsearchAuthorizer.checkPermission()");
+               }
+
+               try {
+                       activatePluginClassLoader();
+
+                       ret = 
rangerElasticsearchAccessControl.checkPermission(user, groups, index, action, 
clientIPAddress);
+               } finally {
+                       deactivatePluginClassLoader();
+               }
+
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerElasticsearchAuthorizer.checkPermission()");
+               }
+
+               return ret;
+       }
+
+       private void activatePluginClassLoader() {
+               if (rangerPluginClassLoader != null) {
+                       
Thread.currentThread().setContextClassLoader(rangerPluginClassLoader);
+               }
+       }
+
+       private void deactivatePluginClassLoader() {
+               if (esClassLoader != null) {
+                       
Thread.currentThread().setContextClassLoader(esClassLoader);
+               }
+       }
+}
diff --git 
a/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/RangerElasticsearchPlugin.java
 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/RangerElasticsearchPlugin.java
new file mode 100644
index 0000000..f9a6837
--- /dev/null
+++ 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/RangerElasticsearchPlugin.java
@@ -0,0 +1,122 @@
+/*
+ * 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.elasticsearch.plugin;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.UnaryOperator;
+
+import org.apache.logging.log4j.Logger;
+import 
org.apache.ranger.authorization.elasticsearch.plugin.action.filter.RangerSecurityActionFilter;
+import 
org.apache.ranger.authorization.elasticsearch.plugin.rest.filter.RangerSecurityRestFilter;
+import org.elasticsearch.action.support.ActionFilter;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.cluster.service.ClusterService;
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.util.concurrent.ThreadContext;
+import org.elasticsearch.common.xcontent.NamedXContentRegistry;
+import org.elasticsearch.env.Environment;
+import org.elasticsearch.env.NodeEnvironment;
+import org.elasticsearch.plugins.ActionPlugin;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.rest.RestHandler;
+import org.elasticsearch.script.ScriptService;
+import org.elasticsearch.threadpool.ThreadPool;
+import org.elasticsearch.watcher.ResourceWatcherService;
+
+public class RangerElasticsearchPlugin extends Plugin implements ActionPlugin {
+
+       private static final Logger LOG = 
ESLoggerFactory.getLogger(RangerElasticsearchPlugin.class);
+
+       private static final String RANGER_ELASTICSEARCH_PLUGIN_CONF_NAME = 
"ranger-elasticsearch-plugin";
+
+       private final Settings settings;
+
+       private RangerSecurityActionFilter rangerSecurityActionFilter;
+
+       public RangerElasticsearchPlugin(Settings settings) {
+               this.settings = settings;
+       }
+
+       @Override
+       public List<ActionFilter> getActionFilters() {
+               return Collections.singletonList(rangerSecurityActionFilter);
+       }
+
+       @Override
+       public UnaryOperator<RestHandler> getRestHandlerWrapper(ThreadContext 
threadContext) {
+               return (UnaryOperator<RestHandler>) (handler -> new 
RangerSecurityRestFilter(this.settings, threadContext,
+                               handler));
+       }
+
+       @Override
+       public Collection<Object> createComponents(final Client client, final 
ClusterService clusterService,
+                       final ThreadPool threadPool, final 
ResourceWatcherService resourceWatcherService,
+                       final ScriptService scriptService, final 
NamedXContentRegistry xContentRegistry,
+                       final Environment environment, final NodeEnvironment 
nodeEnvironment,
+                       final NamedWriteableRegistry namedWriteableRegistry) {
+
+               addPluginConfig2Classpath(environment);
+
+               rangerSecurityActionFilter = new 
RangerSecurityActionFilter(this.settings, threadPool.getThreadContext());
+               return Collections.singletonList(rangerSecurityActionFilter);
+       }
+
+       /**
+        * Add ranger elasticsearch plugin config directory to classpath,
+        * then the plugin can load its configuration files from classpath.
+        */
+       private void addPluginConfig2Classpath(Environment environment) {
+               Path configPath = 
environment.configFile().resolve(RANGER_ELASTICSEARCH_PLUGIN_CONF_NAME);
+               if (configPath == null) {
+                       LOG.error(
+                                       "Failed to add ranger elasticsearch 
plugin config directory [ranger-elasticsearch-plugin] to classpath.");
+                       return;
+               }
+               File configFile = configPath.toFile();
+
+               try {
+                       if (configFile.exists()) {
+                               ClassLoader classLoader = 
this.getClass().getClassLoader();
+                               // This classLoader is FactoryURLClassLoader in 
eleasticsearch
+                               if (classLoader instanceof URLClassLoader) {
+                                       URLClassLoader urlClassLoader = 
(URLClassLoader) classLoader;
+                                       Class<? extends URLClassLoader> 
urlClass = urlClassLoader.getClass();
+                                       Method method = 
urlClass.getSuperclass().getDeclaredMethod("addURL", new Class[] { URL.class });
+                                       method.setAccessible(true);
+                                       method.invoke(urlClassLoader, new 
Object[] { configFile.toURI().toURL() });
+                                       LOG.info("Success to add ranger 
elasticsearch plugin config directory [{}] to classpath.",
+                                                       
configFile.getCanonicalPath());
+                               }
+                       }
+               } catch (Exception e) {
+                       LOG.error(
+                                       "Failed to add ranger elasticsearch 
plugin config directory [ranger-elasticsearch-plugin] to classpath.",
+                                       e);
+                       throw new RuntimeException(e);
+               }
+       }
+}
diff --git 
a/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/action/filter/RangerSecurityActionFilter.java
 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/action/filter/RangerSecurityActionFilter.java
new file mode 100644
index 0000000..60baaea
--- /dev/null
+++ 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/action/filter/RangerSecurityActionFilter.java
@@ -0,0 +1,82 @@
+/*
+ * 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.elasticsearch.plugin.action.filter;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.logging.log4j.Logger;
+import 
org.apache.ranger.authorization.elasticsearch.authorizer.RangerElasticsearchAuthorizer;
+import 
org.apache.ranger.authorization.elasticsearch.plugin.authc.user.UsernamePasswordToken;
+import org.apache.ranger.authorization.elasticsearch.plugin.utils.RequestUtils;
+import org.elasticsearch.ElasticsearchStatusException;
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionResponse;
+import org.elasticsearch.action.support.ActionFilter;
+import org.elasticsearch.action.support.ActionFilterChain;
+import org.elasticsearch.common.component.AbstractComponent;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.util.concurrent.ThreadContext;
+import org.elasticsearch.rest.RestStatus;
+import org.elasticsearch.tasks.Task;
+
+public class RangerSecurityActionFilter extends AbstractComponent implements 
ActionFilter {
+
+       private static final Logger LOG = 
ESLoggerFactory.getLogger(RangerSecurityActionFilter.class);
+
+       private final ThreadContext threadContext;
+
+       private final RangerElasticsearchAuthorizer 
rangerElasticsearchAuthorizer = new RangerElasticsearchAuthorizer();
+
+       public RangerSecurityActionFilter(Settings settings, ThreadContext 
threadContext) {
+               super(settings);
+               this.threadContext = threadContext;
+       }
+
+       @Override
+       public int order() {
+               return 0;
+       }
+
+       @Override
+       public <Request extends ActionRequest, Response extends ActionResponse> 
void apply(Task task, String action,
+                       Request request, ActionListener<Response> listener, 
ActionFilterChain<Request, Response> chain) {
+               String user = 
threadContext.getTransient(UsernamePasswordToken.USERNAME);
+               // If user is not null, then should check permission of the 
outside caller.
+               if (StringUtils.isNotEmpty(user)) {
+                       List<String> indexs = 
RequestUtils.getIndexFromRequest(request);
+                       String clientIPAddress = 
threadContext.getTransient(RequestUtils.CLIENT_IP_ADDRESS);
+                       for (String index : indexs) {
+                               boolean result = 
rangerElasticsearchAuthorizer.checkPermission(user, null, index, action,
+                                               clientIPAddress);
+                               if (!result) {
+                                       String errorMsg = "Error: User[{}] 
could not do action[{}] on index[{}]";
+                                       throw new 
ElasticsearchStatusException(errorMsg, RestStatus.FORBIDDEN, user, action, 
index);
+                               }
+                       }
+               } else {
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("User is null, no check permission 
for elasticsearch do action[{}] with request[{}]", action,
+                                               request);
+                       }
+               }
+               chain.proceed(task, action, request, listener);
+       }
+}
diff --git 
a/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/authc/user/UsernamePasswordToken.java
 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/authc/user/UsernamePasswordToken.java
new file mode 100644
index 0000000..c1df938
--- /dev/null
+++ 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/authc/user/UsernamePasswordToken.java
@@ -0,0 +1,103 @@
+/*
+ * 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.elasticsearch.plugin.authc.user;
+
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticsearchStatusException;
+import org.elasticsearch.rest.RestRequest;
+import org.elasticsearch.rest.RestStatus;
+
+public class UsernamePasswordToken {
+
+       public static final String USERNAME = "username";
+
+       public static final String BASIC_AUTH_PREFIX = "Basic ";
+
+       public static final String BASIC_AUTH_HEADER = "Authorization";
+
+       private String username;
+
+       private String password;
+
+       public UsernamePasswordToken(String username, String password) {
+               this.username = username;
+               this.password = password;
+       }
+
+       public static UsernamePasswordToken parseToken(RestRequest request) {
+
+               Map<String, List<String>> headers = request.getHeaders();
+               if (MapUtils.isEmpty(headers)) {
+                       return null;
+               }
+               List<String> authStrs = headers.get(BASIC_AUTH_HEADER);
+               if (CollectionUtils.isEmpty(authStrs)) {
+                       return null;
+               }
+
+               String authStr = authStrs.get(0);
+               if (StringUtils.isEmpty(authStr)) {
+                       return null;
+               }
+
+               String userPass = "";
+               try {
+                       userPass = new 
String(Base64.getUrlDecoder().decode(authStr.substring(BASIC_AUTH_PREFIX.length())));
+               } catch (IllegalArgumentException e) {
+                       throw new ElasticsearchStatusException("Error: Failed 
to parse user authentication.",
+                                       RestStatus.UNAUTHORIZED, e);
+               }
+
+               int i = StringUtils.indexOf(userPass, ':');
+               if (i <= 0) {
+                       throw new ElasticsearchStatusException(
+                                       "Error: Parse user authentication to 
get the wrong userPass[{}].",
+                                       RestStatus.UNAUTHORIZED, userPass);
+               }
+               return new 
UsernamePasswordToken(StringUtils.substring(userPass, 0, i),
+                               StringUtils.substring(userPass, i + 1, 
userPass.length()));
+
+       }
+
+       public String getUsername() {
+               return username;
+       }
+
+       public void setUsername(String username) {
+               this.username = username;
+       }
+
+       public String getPassword() {
+               return password;
+       }
+
+       public void setPassword(String password) {
+               this.password = password;
+       }
+
+       @Override
+       public String toString() {
+               return "UsernamePasswordToken [username=" + username + ", 
password=" + "******" + "]";
+       }
+}
diff --git 
a/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/rest/filter/RangerSecurityRestFilter.java
 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/rest/filter/RangerSecurityRestFilter.java
new file mode 100644
index 0000000..117356a
--- /dev/null
+++ 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/rest/filter/RangerSecurityRestFilter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.elasticsearch.plugin.rest.filter;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.logging.log4j.Logger;
+import 
org.apache.ranger.authorization.elasticsearch.plugin.authc.user.UsernamePasswordToken;
+import org.apache.ranger.authorization.elasticsearch.plugin.utils.RequestUtils;
+import org.elasticsearch.ElasticsearchStatusException;
+import org.elasticsearch.client.node.NodeClient;
+import org.elasticsearch.common.component.AbstractComponent;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.util.concurrent.ThreadContext;
+import org.elasticsearch.rest.RestChannel;
+import org.elasticsearch.rest.RestHandler;
+import org.elasticsearch.rest.RestRequest;
+import org.elasticsearch.rest.RestStatus;
+
+public class RangerSecurityRestFilter extends AbstractComponent implements 
RestHandler {
+
+       private static final Logger LOG = 
ESLoggerFactory.getLogger(RangerSecurityRestFilter.class);
+
+       private final RestHandler restHandler;
+
+       private final ThreadContext threadContext;
+
+       public RangerSecurityRestFilter(final Settings settings, final 
ThreadContext threadContext,
+                       final RestHandler restHandler) {
+               super(settings);
+               this.restHandler = restHandler;
+               this.threadContext = threadContext;
+       }
+
+       @Override
+       public void handleRequest(final RestRequest request, final RestChannel 
channel, final NodeClient client)
+                       throws Exception {
+               // Now only support to get user from request,
+               // it should work with other elasticsearch identity 
authentication plugins in fact.
+               UsernamePasswordToken user = 
UsernamePasswordToken.parseToken(request);
+               if (user == null) {
+                       throw new ElasticsearchStatusException("Error: User is 
null, the request requires user authentication.",
+                                       RestStatus.UNAUTHORIZED);
+               } else {
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("Success to parse user[{}] from 
request[{}].", user, request);
+                       }
+               }
+               threadContext.putTransient(UsernamePasswordToken.USERNAME, 
user.getUsername());
+
+               String clientIPAddress = 
RequestUtils.getClientIPAddress(request);
+               if (StringUtils.isNotEmpty(clientIPAddress)) {
+                       
threadContext.putTransient(RequestUtils.CLIENT_IP_ADDRESS, clientIPAddress);
+               }
+
+               this.restHandler.handleRequest(request, channel, client);
+       }
+}
diff --git 
a/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/utils/RequestUtils.java
 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/utils/RequestUtils.java
new file mode 100644
index 0000000..8a04b06
--- /dev/null
+++ 
b/ranger-elasticsearch-plugin-shim/src/main/java/org/apache/ranger/authorization/elasticsearch/plugin/utils/RequestUtils.java
@@ -0,0 +1,126 @@
+/*
+ * 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.elasticsearch.plugin.utils;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.DocWriteRequest;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
+import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
+import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
+import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest;
+import org.elasticsearch.action.bulk.BulkRequest;
+import org.elasticsearch.action.get.MultiGetRequest;
+import org.elasticsearch.action.get.MultiGetRequest.Item;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.support.replication.ReplicationRequest;
+import 
org.elasticsearch.action.support.single.instance.InstanceShardOperationRequest;
+import org.elasticsearch.action.support.single.shard.SingleShardRequest;
+import org.elasticsearch.rest.RestRequest;
+
+public class RequestUtils {
+       public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
+
+       public static String getClientIPAddress(RestRequest request) {
+               SocketAddress socketAddress = request.getRemoteAddress();
+               if (socketAddress instanceof InetSocketAddress) {
+                       return ((InetSocketAddress) 
socketAddress).getAddress().getHostAddress();
+               }
+
+               return null;
+       }
+
+       // To support all kinds of request in elasticsearch
+       public static <Request extends ActionRequest> List<String> 
getIndexFromRequest(Request request) {
+               List<String> indexs = new ArrayList<>();
+
+               if (request instanceof SingleShardRequest) {
+                       indexs.add(((SingleShardRequest<?>) request).index());
+                       return indexs;
+               }
+
+               if (request instanceof ReplicationRequest) {
+                       indexs.add(((ReplicationRequest<?>) request).index());
+                       return indexs;
+               }
+
+               if (request instanceof InstanceShardOperationRequest) {
+                       indexs.add(((InstanceShardOperationRequest<?>) 
request).index());
+                       return indexs;
+               }
+
+               if (request instanceof CreateIndexRequest) {
+                       indexs.add(((CreateIndexRequest) request).index());
+                       return indexs;
+               }
+
+               if (request instanceof PutMappingRequest) {
+                       indexs.add(((PutMappingRequest) 
request).getConcreteIndex().getName());
+                       return indexs;
+               }
+
+               if (request instanceof SearchRequest) {
+                       return Arrays.asList(((SearchRequest) 
request).indices());
+               }
+
+               if (request instanceof IndicesStatsRequest) {
+                       return Arrays.asList(((IndicesStatsRequest) 
request).indices());
+               }
+
+               if (request instanceof OpenIndexRequest) {
+                       return Arrays.asList(((OpenIndexRequest) 
request).indices());
+               }
+
+               if (request instanceof DeleteIndexRequest) {
+                       return Arrays.asList(((DeleteIndexRequest) 
request).indices());
+               }
+
+               if (request instanceof BulkRequest) {
+                       @SuppressWarnings("rawtypes")
+                       List<DocWriteRequest> requests = ((BulkRequest) 
request).requests();
+
+                       if (CollectionUtils.isNotEmpty(requests)) {
+                               for (DocWriteRequest<?> docWriteRequest : 
requests) {
+                                       indexs.add(docWriteRequest.index());
+                               }
+                               return indexs;
+                       }
+               }
+
+               if (request instanceof MultiGetRequest) {
+                       List<Item> items = ((MultiGetRequest) 
request).getItems();
+                       if (CollectionUtils.isNotEmpty(items)) {
+                               for (Item item : items) {
+                                       indexs.add(item.index());
+                               }
+                               return indexs;
+                       }
+               }
+
+               // No matched request type to find specific index , set default 
value *
+               indexs.add("*");
+               return indexs;
+       }
+}
diff --git a/src/main/assembly/admin-web.xml b/src/main/assembly/admin-web.xml
index b3ec885..8ea728b 100644
--- a/src/main/assembly/admin-web.xml
+++ b/src/main/assembly/admin-web.xml
@@ -376,6 +376,18 @@
           </includes>
       </moduleSet>
 
+      <moduleSet>
+          <binaries>
+              <includeDependencies>true</includeDependencies>
+              
<outputDirectory>/ews/webapp/WEB-INF/classes/ranger-plugins/elasticsearch</outputDirectory>
+              <unpack>false</unpack>
+              <directoryMode>755</directoryMode>
+              <fileMode>644</fileMode>
+          </binaries>
+          <includes>
+              <include>org.apache.ranger:ranger-elasticsearch-plugin</include>
+          </includes>
+      </moduleSet>
   </moduleSets>
 
   <fileSets>
diff --git a/src/main/assembly/plugin-elasticsearch.xml 
b/src/main/assembly/plugin-elasticsearch.xml
new file mode 100644
index 0000000..41f73a3
--- /dev/null
+++ b/src/main/assembly/plugin-elasticsearch.xml
@@ -0,0 +1,197 @@
+<?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>elasticsearch-plugin</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    
<baseDirectory>${project.name}-${project.version}-elasticsearch-plugin</baseDirectory>
+    <includeBaseDirectory>true</includeBaseDirectory>
+  <moduleSets>
+    <moduleSet>
+    <binaries>
+        <includeDependencies>false</includeDependencies>
+        <unpack>false</unpack>
+        <directoryMode>755</directoryMode>
+        <fileMode>644</fileMode>
+        <dependencySets>
+            <dependencySet>
+                
<outputDirectory>/lib/ranger-elasticsearch-plugin</outputDirectory>
+                <unpack>false</unpack>
+                <includes>
+                    <include>commons-collections:commons-collections</include>
+                    <include>commons-lang:commons-lang</include>
+                    <include>org.slf4j:slf4j-api</include>
+                                       
<include>org.slf4j:slf4j-log4j12</include>
+                </includes>
+            </dependencySet>
+        </dependencySets>
+        <outputDirectory>/lib/ranger-elasticsearch-plugin</outputDirectory>
+    </binaries>
+    <includes>
+        <include>org.apache.ranger:ranger-elasticsearch-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-elasticsearch-plugin/ranger-elasticsearch-plugin-impl</outputDirectory>
+                <unpack>false</unpack>
+                <includes>
+                    
<include>commons-configuration:commons-configuration:jar:${commons.configuration.version}</include>
+                    
<include>org.apache.hadoop:hadoop-common:jar:${hadoop.version}</include>
+                    
<include>org.apache.hadoop:hadoop-common-plus:jar:${hadoop.version}</include>
+                    
<include>org.apache.hadoop:hadoop-auth:jar:${hadoop.version}</include>
+                    
<include>org.apache.hadoop:hadoop-hdfs:jar:${hadoop.version}</include>
+                    <include>com.google.code.gson:gson</include>
+                    <include>org.eclipse.persistence:eclipselink</include>
+                    
<include>org.eclipse.persistence:javax.persistence</include>
+                    <include>com.sun.jersey:jersey-bundle</include>
+                    
<include>commons-logging:commons-logging:jar:${commons.logging.version}</include>
+                    <include>commons-io:commons-io</include>
+                    
<include>com.google.guava:guava:jar:${google.guava.version}</include>
+                    
<include>org.apache.httpcomponents:httpclient:jar:${httpcomponents.httpclient.version}</include>
+                    
<include>org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version}</include>
+                    
<include>org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version}</include>
+                    <include>org.noggit:noggit:jar:${noggit.version}</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.solr:solr-solrj</include>
+                    <include>commons-codec:commons-codec</include>
+                </includes>
+            </dependencySet>
+            <dependencySet>
+                <outputDirectory>/install/lib</outputDirectory>
+                <unpack>false</unpack>
+                <directoryMode>755</directoryMode>
+                <fileMode>644</fileMode>
+                <includes>
+                    <include>commons-cli:commons-cli</include>
+                    <include>commons-collections:commons-collections</include>
+                    
<include>commons-configuration:commons-configuration: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.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.apache.ranger:ranger-plugins-cred</include>
+                    <include>org.apache.ranger:credentialbuilder</include>
+                </includes>
+            </dependencySet>
+        </dependencySets>
+        
<outputDirectory>/lib/ranger-elasticsearch-plugin/ranger-elasticsearch-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-elasticsearch-plugin</include>
+    </includes>
+    </moduleSet>
+    <moduleSet>
+    <binaries>
+        <includeDependencies>true</includeDependencies>
+        <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-elasticsearch/conf</directory>
+        <excludes>
+            <exclude>*.sh</exclude>
+        </excludes>
+        <fileMode>700</fileMode>
+    </fileSet>
+    <fileSet>
+        <outputDirectory>/install/conf.templates/disable</outputDirectory>
+        <directory>plugin-elasticsearch/disable-conf</directory>
+        <fileMode>700</fileMode>
+    </fileSet>
+    <fileSet>
+        <outputDirectory>/install/conf.templates/default</outputDirectory>
+        <directory>plugin-elasticsearch/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-elasticsearch-plugin.sh</destName>
+        <fileMode>755</fileMode>
+    </file>
+    <file>
+        <source>agents-common/scripts/enable-agent.sh</source>
+        <outputDirectory>/</outputDirectory>
+        <destName>disable-elasticsearch-plugin.sh</destName>
+        <fileMode>755</fileMode>
+    </file>
+    <file>
+        <source>plugin-elasticsearch/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>
+    <file>
+        
<source>ranger-elasticsearch-plugin-shim/conf/plugin-descriptor.properties</source>
+        <outputDirectory>/lib/ranger-elasticsearch-plugin</outputDirectory>
+        <fileMode>755</fileMode>
+        <filtered>true</filtered>
+    </file>
+    <file>
+        
<source>ranger-elasticsearch-plugin-shim/conf/plugin-security.policy</source>
+        <outputDirectory>/lib/ranger-elasticsearch-plugin</outputDirectory>
+        <fileMode>755</fileMode>
+    </file>
+  </files>
+</assembly>

Reply via email to