You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by fo...@apache.org on 2020/04/04 16:02:41 UTC

[druid] branch master updated: Add Apache Ranger Authorization (#9579)

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

fokko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 2d99966  Add Apache Ranger Authorization (#9579)
2d99966 is described below

commit 2d999669333fc7bd344e5bec0d74f0fbcd916272
Author: bolkedebruin <bo...@users.noreply.github.com>
AuthorDate: Sat Apr 4 18:02:24 2020 +0200

    Add Apache Ranger Authorization (#9579)
---
 distribution/bin/check-licenses.py                 |   4 +
 distribution/pom.xml                               |   2 +
 .../extensions-core/druid-ranger-security.md       | 158 ++++++++
 docs/development/extensions.md                     |   1 +
 extensions-core/druid-ranger-security/pom.xml      | 406 +++++++++++++++++++++
 .../ranger/authorizer/RangerAuthorizer.java        | 140 +++++++
 .../authorizer/RangerSecurityDruidModule.java      |  90 +++++
 .../security/ranger/authorizer/guice/Ranger.java   |  34 ++
 .../org.apache.druid.initialization.DruidModule    |  16 +
 .../ranger/authorizer/RangerAdminClientImpl.java   |  68 ++++
 .../ranger/authorizer/RangerAuthorizerTest.java    |  60 +++
 .../src/test/resources/druid-policies.json         | 294 +++++++++++++++
 .../src/test/resources/ranger-druid-security.xml   |  52 +++
 licenses.yaml                                      | 232 ++++++++++++
 pom.xml                                            |   3 +
 website/.spelling                                  |   6 +-
 16 files changed, 1565 insertions(+), 1 deletion(-)

diff --git a/distribution/bin/check-licenses.py b/distribution/bin/check-licenses.py
index f90ecd8..5704adc 100755
--- a/distribution/bin/check-licenses.py
+++ b/distribution/bin/check-licenses.py
@@ -224,6 +224,7 @@ def build_compatible_license_names():
     compatible_licenses['Apache License Version 2'] = 'Apache License version 2.0'
     compatible_licenses['Apache License v2.0'] = 'Apache License version 2.0'
     compatible_licenses['Apache License, version 2.0'] = 'Apache License version 2.0'
+    compatible_licenses['Apache 2.0 License'] = 'Apache License version 2.0'
 
     compatible_licenses['Public Domain'] = 'Public Domain'
 
@@ -241,6 +242,7 @@ def build_compatible_license_names():
     compatible_licenses['Revised BSD'] = 'BSD-3-Clause License'
     compatible_licenses['New BSD License'] = 'BSD-3-Clause License'
     compatible_licenses['3-Clause BSD License'] = 'BSD-3-Clause License'
+    compatible_licenses['BSD 3-Clause'] = 'BSD-3-Clause License'
 
     compatible_licenses['ICU License'] = 'ICU License'
 
@@ -256,9 +258,11 @@ def build_compatible_license_names():
     compatible_licenses['The Eclipse Public License, Version 1.0'] = 'Eclipse Public License 1.0'
     compatible_licenses['Eclipse Public License - Version 1.0'] = 'Eclipse Public License 1.0'
     compatible_licenses['Eclipse Public License, Version 1.0'] = 'Eclipse Public License 1.0'
+    compatible_licenses['Eclipse Public License v1.0'] = 'Eclipse Public License 1.0'
 
     compatible_licenses['Eclipse Distribution License 1.0'] = 'Eclipse Distribution License 1.0'
     compatible_licenses['Eclipse Distribution License - v 1.0'] = 'Eclipse Distribution License 1.0'
+    compatible_licenses['Eclipse Distribution License v. 1.0'] = 'Eclipse Distribution License 1.0'
     compatible_licenses['EDL 1.0'] = 'Eclipse Distribution License 1.0'
 
     compatible_licenses['Mozilla Public License Version 2.0'] = 'Mozilla Public License Version 2.0'
diff --git a/distribution/pom.xml b/distribution/pom.xml
index 4ecc7c3..a47ead3 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -242,6 +242,8 @@
                                         <argument>org.apache.druid.extensions:druid-basic-security</argument>
                                         <argument>-c</argument>
                                         <argument>org.apache.druid.extensions:druid-pac4j</argument>
+                                        <argument>-c</argument>
+                                        <argument>org.apache.druid.extensions:druid-ranger-security</argument>
                                         <argument>${druid.distribution.pulldeps.opts}</argument>
                                     </arguments>
                                 </configuration>
diff --git a/docs/development/extensions-core/druid-ranger-security.md b/docs/development/extensions-core/druid-ranger-security.md
new file mode 100644
index 0000000..374458f
--- /dev/null
+++ b/docs/development/extensions-core/druid-ranger-security.md
@@ -0,0 +1,158 @@
+---
+id: druid-ranger-security
+title: "Apache Ranger Security"
+---
+
+<!--
+  ~ 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.
+  -->
+  
+This Apache Druid extension adds:
+
+- an Authorizer which implements access control for the Druid metastore against Apache Ranger
+
+Make sure to [include](../../development/extensions.md#loading-extensions) `druid-ranger-security` as an extension.
+
+Please see [Authentication and Authorization](../../design/auth.md) for more information on the extension interfaces being implemented.
+
+## Configuration
+
+Support for Apache Ranger authorization consists of three elements: configuration of the extension 
+in Apache Druid, configuring the connection to Apache Ranger and providing the service definition for Druid to Apache Ranger.
+ 
+### Enabling the extension
+Ensure that you have a valid authentication chain and escalator set in your `common.runtime.properties`. For every 
+authenticator your wish to use the authorizer for set `druid.auth.authenticator.<authenticatorName>.authorizerName` 
+to the name you will give the authorizer, e.g. `ranger`. 
+
+Then add the following and amend to your needs (in case you use multiple authorizers):
+
+```
+druid.auth.authorizers=["ranger"]
+druid.auth.authorizer.ranger.type=ranger
+```
+
+The following is an example that uses `druid-basic-security` for authentication and `druid-ranger-security` for 
+authorization.
+
+```
+druid.auth.authenticatorChain=["basic"]
+druid.auth.authenticator.basic.type=basic
+druid.auth.authenticator.basic.initialAdminPassword=password1
+druid.auth.authenticator.basic.initialInternalClientPassword=password2
+druid.auth.authenticator.basic.credentialsValidator.type=metadata
+druid.auth.authenticator.basic.skipOnFailure=false
+druid.auth.authenticator.basic.enableCacheNotifications=true
+druid.auth.authenticator.basic.authorizerName=ranger
+
+druid.auth.authorizers=["ranger"]
+druid.auth.authorizer.ranger.type=ranger
+
+# Escalator
+druid.escalator.type=basic
+druid.escalator.internalClientUsername=druid_system
+druid.escalator.internalClientPassword=password2
+druid.escalator.authorizerName=ranger
+```
+
+---
+**NOTE**
+
+Contrary to the documentation of `druid-basic-auth` Ranger does not automatically provision a highly privileged
+system system user and you will need to do this yourself. This system user in case of `druid-basic-auth` is named 
+`druid_system` and for the escalator it is configurable as shown above. Make sure to take note of these user names and 
+configure `READ` access to `state:STATE` and to `config:security` in your ranger policies, 
+otherwise system services will not work properly.
+---
+
+#### Properties to configure the extension in Apache Druid
+|Property|Description|Default|required|
+|--------|-----------|-------|--------|
+|`druid.auth.ranger.keytab`|Defines the keytab to be used while authenticating against Apache Ranger to obtain policies and provide auditing|null|No|
+|`druid.auth.ranger.principal`|Defines the principal to be used while authenticating against Apache Ranger to obtain policies and provide auditing|null|No|
+|`druid.auth.ranger.use_ugi`|Determines if groups that the authenticated user belongs to should be obtained from Hadoop's `UserGroupInformation`|null|No|
+
+### Configuring the connection to Apache Ranger
+
+The Apache Ranger authorization extension will read several configuration files. Discussing the
+the contents of those files is beyond the scope of this document. Depending on your needs you will 
+need to create them. The minimum you will need to have is a `ranger-druid-security.xml` file 
+that you will need to put in the classpath (e.g. `_common`). For auditing, the configuration is 
+in `ranger-druid-audit.xml`.
+
+### Adding the service definition for Apache Druid to Apache Ranger
+
+At the time of writing of this document Apache Ranger (2.0) does not include a service and 
+service definition yet. You can add the service definition to Apache Ranger by entering the following
+command:
+
+`curl -u <user>:<password> -d "@ranger-servicedef-druid.json" -X POST -H "Accept: application/json" -H "Content-Type: application/json" http://localhost:6080/service/public/v2/api/servicedef/`
+
+You should get back `json` describing the service definition you just added. You can now go to the web
+interface of Apache Ranger which should now include a widget for "Druid". Click the plus sign an create
+the new service. Ensure your service name is equal to what you configured in `ranger-druid-security.xml`.
+
+#### Configuring Apache Ranger policies
+
+When installing a new Druid service inside Apache Ranger for the first time, Ranger will provision the policies
+to allow the administrative user `read/write` access to all properties and data sources. You might want to limit this.
+Do not forget to add the correct policies for the `druid_system` user and the `internalClientUserName` of the escalator.
+
+---
+**NOTE**
+
+Loading new data sources requires `write` access to the `datasource` prior to the loading itself. So if you
+want to create a datasource `wikipedia` you are required to have an `allow` policy inside Apache Ranger before
+trying to load the spec. 
+---
+
+## Usage
+
+### HTTP methods
+
+For information on what HTTP methods are supported on a particular request endpoint, please refer to the [API documentation](../../operations/api-reference.md).
+
+GET requires READ permission, while POST and DELETE require WRITE permission.
+
+### SQL Permissions
+
+Queries on Druid datasources require DATASOURCE READ permissions for the specified datasource.
+
+Queries on the [INFORMATION_SCHEMA tables](../../querying/sql.html#information-schema) will
+return information about datasources that the caller has DATASOURCE READ access to. Other
+datasources will be omitted.
+
+Queries on the [system schema tables](../../querying/sql.html#system-schema) require the following permissions:
+- `segments`: Segments will be filtered based on DATASOURCE READ permissions.
+- `servers`: The user requires STATE READ permissions.
+- `server_segments`: The user requires STATE READ permissions and segments will be filtered based on DATASOURCE READ permissions.
+- `tasks`: Tasks will be filtered based on DATASOURCE READ permissions.
+
+
+### Debugging
+
+If you face difficulty grasping why access is denied to certain elements and the `audit` section in
+Apache Ranger does not give you any detail, you can enable debug logging for `org.apache.druid.security.ranger`.
+To do so add the following in your `log4j2.xml`:
+
+```xml
+<!-- Set level="debug" to see access requests to Apache Ranger -->
+<Logger name="org.apache.druid.security" level="debug" additivity="false">
+  <Appender-ref ref="Console"/>
+</Logger>
+```
diff --git a/docs/development/extensions.md b/docs/development/extensions.md
index 21bd850..54a50ff 100644
--- a/docs/development/extensions.md
+++ b/docs/development/extensions.md
@@ -54,6 +54,7 @@ Core extensions are maintained by Druid committers.
 |druid-orc-extensions|Support for data in Apache Orc data format.|[link](../development/extensions-core/orc.md)|
 |druid-parquet-extensions|Support for data in Apache Parquet data format. Requires druid-avro-extensions to be loaded.|[link](../development/extensions-core/parquet.md)|
 |druid-protobuf-extensions| Support for data in Protobuf data format.|[link](../development/extensions-core/protobuf.md)|
+|druid-ranger-security|Support for access control through Apache Ranger.|[link](../development/extensions-core/druid-ranger-security.md)|
 |druid-s3-extensions|Interfacing with data in AWS S3, and using S3 as deep storage.|[link](../development/extensions-core/s3.md)|
 |druid-ec2-extensions|Interfacing with AWS EC2 for autoscaling middle managers|UNDOCUMENTED|
 |druid-stats|Statistics related module including variance and standard deviation.|[link](../development/extensions-core/stats.md)|
diff --git a/extensions-core/druid-ranger-security/pom.xml b/extensions-core/druid-ranger-security/pom.xml
new file mode 100644
index 0000000..fa6c825
--- /dev/null
+++ b/extensions-core/druid-ranger-security/pom.xml
@@ -0,0 +1,406 @@
+<?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>
+
+    <groupId>org.apache.druid.extensions</groupId>
+    <artifactId>druid-ranger-security</artifactId>
+    <name>druid-ranger-security</name>
+    <description>druid-ranger-security</description>
+
+    <parent>
+        <groupId>org.apache.druid</groupId>
+        <artifactId>druid</artifactId>
+        <version>0.19.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.druid</groupId>
+            <artifactId>druid-core</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.druid</groupId>
+            <artifactId>druid-services</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.druid</groupId>
+            <artifactId>druid-server</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jdbi</groupId>
+            <artifactId>jdbi</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-smile</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-server</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>jsr311-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ranger</groupId>
+            <artifactId>ranger-plugins-common</artifactId>
+            <version>${apache.ranger.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ranger</groupId>
+            <artifactId>ranger-plugins-audit</artifactId>
+            <version>${apache.ranger.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${apache.ranger.gson.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-client</artifactId>
+            <scope>runtime</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>commons-cli</groupId>
+                    <artifactId>commons-cli</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-codec</groupId>
+                    <artifactId>commons-codec</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-logging</groupId>
+                    <artifactId>commons-logging</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-io</groupId>
+                    <artifactId>commons-io</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-lang</groupId>
+                    <artifactId>commons-lang</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpclient</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpcore</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.zookeeper</groupId>
+                    <artifactId>zookeeper</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.ws.rs</groupId>
+                    <artifactId>jsr311-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>jsr305</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.mortbay.jetty</groupId>
+                    <artifactId>jetty-util</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.hadoop</groupId>
+                    <artifactId>hadoop-annotations</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.activation</groupId>
+                    <artifactId>activation</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.protobuf</groupId>
+                    <artifactId>protobuf-java</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.sun.jersey</groupId>
+                    <artifactId>jersey-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.curator</groupId>
+                    <artifactId>curator-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.curator</groupId>
+                    <artifactId>curator-framework</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.curator</groupId>
+                    <artifactId>curator-recipes</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.commons</groupId>
+                    <artifactId>commons-math3</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+                <!-- Following are excluded to remove security vulnerabilities: -->
+                <exclusion>
+                    <groupId>commons-beanutils</groupId>
+                    <artifactId>commons-beanutils-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-common</artifactId>
+            <version>${hadoop.compile.version}</version>
+            <scope>compile</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>commons-cli</groupId>
+                    <artifactId>commons-cli</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-codec</groupId>
+                    <artifactId>commons-codec</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-logging</groupId>
+                    <artifactId>commons-logging</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-io</groupId>
+                    <artifactId>commons-io</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-lang</groupId>
+                    <artifactId>commons-lang</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpclient</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpcore</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.zookeeper</groupId>
+                    <artifactId>zookeeper</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.ws.rs</groupId>
+                    <artifactId>jsr311-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>jsr305</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.mortbay.jetty</groupId>
+                    <artifactId>jetty-util</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.protobuf</groupId>
+                    <artifactId>protobuf-java</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.sun.jersey</groupId>
+                    <artifactId>jersey-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.curator</groupId>
+                    <artifactId>curator-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.commons</groupId>
+                    <artifactId>commons-math3</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.avro</groupId>
+                    <artifactId>avro</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>net.java.dev.jets3t</groupId>
+                    <artifactId>jets3t</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.sun.jersey</groupId>
+                    <artifactId>jersey-json</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.jcraft</groupId>
+                    <artifactId>jsch</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.mortbay.jetty</groupId>
+                    <artifactId>jetty</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.sun.jersey</groupId>
+                    <artifactId>jersey-server</artifactId>
+                </exclusion>
+                <!-- Following are excluded to remove security vulnerabilities: -->
+                <exclusion>
+                    <groupId>commons-beanutils</groupId>
+                    <artifactId>commons-beanutils-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- Tests -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.druid</groupId>
+            <artifactId>druid-server</artifactId>
+            <version>${project.parent.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <testResources>
+            <testResource>
+                <directory>src/test/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+                <filtering>true</filtering>
+            </testResource>
+        </testResources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <configuration>
+                    <usedDependencies>
+                        <!-- These are needed for scope: compile -->
+                        <dependency>org.apache.ranger:ranger-plugins-audit</dependency>
+                    </usedDependencies>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizer.java b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizer.java
new file mode 100644
index 0000000..330a7c0
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizer.java
@@ -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.
+ */
+
+package org.apache.druid.security.ranger.authorizer;
+
+import com.fasterxml.jackson.annotation.JacksonInject;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import org.apache.druid.java.util.common.IAE;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.security.ranger.authorizer.guice.Ranger;
+import org.apache.druid.server.security.Access;
+import org.apache.druid.server.security.Action;
+import org.apache.druid.server.security.AuthenticationResult;
+import org.apache.druid.server.security.Authorizer;
+import org.apache.druid.server.security.Resource;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+@JsonTypeName("ranger")
+public class RangerAuthorizer implements Authorizer
+{
+  private static final Logger log = new Logger(RangerAuthorizer.class);
+
+  public static final String RANGER_DRUID_SERVICETYPE = "druid";
+  public static final String RANGER_DRUID_APPID = "druid";
+
+  private final RangerBasePlugin rangerPlugin;
+  private final boolean useUgi;
+
+  @JsonCreator
+  public RangerAuthorizer(
+      @JsonProperty("keytab") String keytab,
+      @JsonProperty("principal") String principal,
+      @JsonProperty("use_ugi") boolean useUgi,
+      @JacksonInject @Ranger Configuration conf)
+  {
+    this.useUgi = useUgi;
+
+    UserGroupInformation.setConfiguration(conf);
+
+    if (keytab != null && principal != null) {
+      try {
+        UserGroupInformation.loginUserFromKeytab(principal, keytab);
+      }
+      catch (IOException ioe) {
+        throw new RuntimeException(ioe);
+      }
+    }
+
+    rangerPlugin = new RangerBasePlugin(RANGER_DRUID_SERVICETYPE, RANGER_DRUID_APPID);
+    rangerPlugin.init();
+    rangerPlugin.setResultProcessor(new RangerDefaultAuditHandler());
+
+  }
+
+  @Override
+  public Access authorize(AuthenticationResult authenticationResult, Resource resource, Action action)
+  {
+    if (authenticationResult == null) {
+      throw new IAE("authenticationResult is null where it should never be.");
+    }
+
+    Set<String> userGroups = null;
+    if (useUgi) {
+      UserGroupInformation ugi = UserGroupInformation.createRemoteUser(authenticationResult.getIdentity());
+      String[] groups = ugi != null ? ugi.getGroupNames() : null;
+      if (groups != null && groups.length > 0) {
+        userGroups = new HashSet<>(Arrays.asList(groups));
+      }
+    }
+
+    RangerDruidResource rangerDruidResource = new RangerDruidResource(resource);
+    RangerDruidAccessRequest request = new RangerDruidAccessRequest(
+        rangerDruidResource,
+        authenticationResult.getIdentity(),
+        userGroups,
+        action
+    );
+
+    RangerAccessResult result = rangerPlugin.isAccessAllowed(request);
+    if (log.isDebugEnabled()) {
+      log.debug("==> authorize: %s, allowed: %s",
+          request.toString(),
+          result != null ? result.getIsAllowed() : null);
+    }
+
+    if (result != null && result.getIsAllowed()) {
+      return new Access(true);
+    }
+
+    return new Access(false);
+  }
+}
+
+class RangerDruidResource extends RangerAccessResourceImpl
+{
+  public RangerDruidResource(Resource resource)
+  {
+    setValue(resource.getType().name().toLowerCase(Locale.ENGLISH), resource.getName());
+  }
+}
+
+class RangerDruidAccessRequest extends RangerAccessRequestImpl
+{
+  public RangerDruidAccessRequest(RangerDruidResource resource, String user, Set<String> userGroups, Action action)
+  {
+    super(resource, action.name().toLowerCase(Locale.ENGLISH), user, userGroups);
+    setAccessTime(new Date());
+  }
+}
diff --git a/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerSecurityDruidModule.java b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerSecurityDruidModule.java
new file mode 100644
index 0000000..f10ddeb
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerSecurityDruidModule.java
@@ -0,0 +1,90 @@
+/*
+ * 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.druid.security.ranger.authorizer;
+
+import com.fasterxml.jackson.databind.Module;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Binder;
+import com.google.inject.Inject;
+import org.apache.druid.initialization.DruidModule;
+import org.apache.druid.security.ranger.authorizer.guice.Ranger;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+
+public class RangerSecurityDruidModule implements DruidModule
+{
+  private Properties props = null;
+
+  @Override
+  public void configure(Binder binder)
+  {
+    // this block of code is common among extensions that use Hadoop things but are not running in Hadoop, in order
+    // to properly initialize everything
+
+    final Configuration conf = new Configuration();
+
+    // Set explicit CL. Otherwise it'll try to use thread context CL, which may not have all of our dependencies.
+    conf.setClassLoader(getClass().getClassLoader());
+
+    // Ensure that FileSystem class level initialization happens with correct CL
+    // See https://github.com/apache/druid/issues/1714
+    ClassLoader currCtxCl = Thread.currentThread().getContextClassLoader();
+    try {
+      Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+      FileSystem.get(conf);
+    }
+    catch (IOException ex) {
+      throw new RuntimeException(ex);
+    }
+    finally {
+      Thread.currentThread().setContextClassLoader(currCtxCl);
+    }
+
+    if (props != null) {
+      for (String propName : props.stringPropertyNames()) {
+        if (propName.startsWith("hadoop.")) {
+          conf.set(propName.substring("hadoop.".length()), props.getProperty(propName));
+        }
+      }
+    }
+
+    binder.bind(Configuration.class).annotatedWith(Ranger.class).toInstance(conf);
+  }
+
+  @Override
+  public List<? extends Module> getJacksonModules()
+  {
+    return ImmutableList.of(
+      new SimpleModule("RangerDruidSecurity").registerSubtypes(RangerAuthorizer.class)
+    );
+  }
+
+  @Inject
+  public void setProperties(Properties props)
+  {
+    this.props = props;
+  }
+
+}
diff --git a/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/guice/Ranger.java b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/guice/Ranger.java
new file mode 100644
index 0000000..811a00b
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/guice/Ranger.java
@@ -0,0 +1,34 @@
+/*
+ * 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.druid.security.ranger.authorizer.guice;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@BindingAnnotation
+public @interface Ranger
+{
+}
diff --git a/extensions-core/druid-ranger-security/src/main/resources/META-INF/services/org.apache.druid.initialization.DruidModule b/extensions-core/druid-ranger-security/src/main/resources/META-INF/services/org.apache.druid.initialization.DruidModule
new file mode 100644
index 0000000..62de1db
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/main/resources/META-INF/services/org.apache.druid.initialization.DruidModule
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+org.apache.druid.security.ranger.authorizer.RangerSecurityDruidModule
diff --git a/extensions-core/druid-ranger-security/src/test/java/org/apache/druid/security/ranger/authorizer/RangerAdminClientImpl.java b/extensions-core/druid-ranger-security/src/test/java/org/apache/druid/security/ranger/authorizer/RangerAdminClientImpl.java
new file mode 100644
index 0000000..c28bdc3
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/test/java/org/apache/druid/security/ranger/authorizer/RangerAdminClientImpl.java
@@ -0,0 +1,68 @@
+/*
+ * 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.druid.security.ranger.authorizer;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.ranger.admin.client.AbstractRangerAdminClient;
+import org.apache.ranger.plugin.util.ServicePolicies;
+
+import java.io.File;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class RangerAdminClientImpl extends AbstractRangerAdminClient
+{
+  private static final Logger LOG = new Logger(RangerAdminClientImpl.class);
+  private static final String CACHE_FILE_NAME = "druid-policies.json";
+
+  protected Gson gson;
+
+  @Override
+  public void init(String serviceName, String appId, String configPropertyPrefix)
+  {
+    super.init(serviceName, appId, configPropertyPrefix);
+
+    try {
+      gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").setPrettyPrinting().create();
+    }
+    catch (Throwable excp) {
+      LOG.error(excp, "AbstractRangerAdminClient: failed to create GsonBuilder object");
+    }
+  }
+
+  @Override
+  public ServicePolicies getServicePoliciesIfUpdated(long lastKnownVersion, long lastActivationTimeInMillis) throws Exception
+  {
+
+    String basedir = System.getProperty("basedir");
+    if (basedir == null) {
+      basedir = new File(".").getCanonicalPath();
+    }
+
+    Path cachePath = FileSystems.getDefault().getPath(basedir, "/src/test/resources/" + CACHE_FILE_NAME);
+    byte[] cacheBytes = Files.readAllBytes(cachePath);
+
+    return gson.fromJson(new String(cacheBytes, "UTF8"), ServicePolicies.class);
+  }
+
+}
diff --git a/extensions-core/druid-ranger-security/src/test/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizerTest.java b/extensions-core/druid-ranger-security/src/test/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizerTest.java
new file mode 100644
index 0000000..46fef6c
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/test/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizerTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.druid.security.ranger.authorizer;
+
+import org.apache.druid.server.security.Action;
+import org.apache.druid.server.security.AuthenticationResult;
+import org.apache.druid.server.security.Resource;
+import org.apache.druid.server.security.ResourceType;
+import org.apache.hadoop.conf.Configuration;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class RangerAuthorizerTest
+{
+  static RangerAuthorizer rangerAuthorizer = null;
+
+  private static final AuthenticationResult alice = new AuthenticationResult("alice", null, null, null);
+  private static final AuthenticationResult bob = new AuthenticationResult("bob", null, null, null);
+
+  private static final Resource aliceDatasource = new Resource("alice-datasource", ResourceType.DATASOURCE);
+  private static final Resource aliceConfig = new Resource("config", ResourceType.CONFIG);
+  private static final Resource aliceState = new Resource("state", ResourceType.STATE);
+
+  @BeforeClass
+  public static void setupBeforeClass()
+  {
+    rangerAuthorizer = new RangerAuthorizer(null, null, false, new Configuration());
+  }
+
+  @Test
+  public void testOperations()
+  {
+    Assert.assertTrue(rangerAuthorizer.authorize(alice, aliceDatasource, Action.READ).isAllowed());
+    Assert.assertTrue(rangerAuthorizer.authorize(alice, aliceDatasource, Action.READ).isAllowed());
+    Assert.assertTrue(rangerAuthorizer.authorize(alice, aliceConfig, Action.READ).isAllowed());
+    Assert.assertTrue(rangerAuthorizer.authorize(alice, aliceConfig, Action.WRITE).isAllowed());
+    Assert.assertTrue(rangerAuthorizer.authorize(alice, aliceState, Action.READ).isAllowed());
+    Assert.assertTrue(rangerAuthorizer.authorize(alice, aliceState, Action.WRITE).isAllowed());
+
+    Assert.assertFalse(rangerAuthorizer.authorize(bob, aliceDatasource, Action.READ).isAllowed());
+  }
+}
diff --git a/extensions-core/druid-ranger-security/src/test/resources/druid-policies.json b/extensions-core/druid-ranger-security/src/test/resources/druid-policies.json
new file mode 100644
index 0000000..abdf85a
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/test/resources/druid-policies.json
@@ -0,0 +1,294 @@
+{
+  "serviceName": "cl1_druid",
+  "serviceId": 16,
+  "policyUpdateTime": "20180304-09:49:38.000-+0000",
+  "policyVersion": "1",
+  "policies": [
+    {
+      "service": "cl1_druid",
+      "name": "alice-test",
+      "policyType": 0,
+      "policyPriority": 0,
+      "description": "",
+      "isAuditEnabled": true,
+      "resources": {
+        "datasource": {
+          "values": [
+            "alice-datasource"
+          ],
+          "isExcludes": false,
+          "isRecursive": false
+        }
+      },
+      "policyItems": [
+        {
+          "accesses": [
+            {
+              "type": "read",
+              "isAllowed": true
+            }
+          ],
+          "users": [
+            "alice"
+          ],
+          "groups": [],
+          "roles": [],
+          "conditions": [],
+          "delegateAdmin": false
+        }
+      ],
+      "denyPolicyItems": [],
+      "allowExceptions": [],
+      "denyExceptions": [],
+      "dataMaskPolicyItems": [],
+      "rowFilterPolicyItems": [],
+      "serviceType": "druid",
+      "options": {},
+      "validitySchedules": [],
+      "policyLabels": [],
+      "zoneName": "",
+      "isDenyAllElse": false,
+      "id": 62,
+      "guid": "850fe929-26ce-4641-be06-3a771b969e54",
+      "isEnabled": true,
+      "version": 1
+    },
+    {
+      "service": "cl1_druid",
+      "name": "alice-config",
+      "policyType": 0,
+      "policyPriority": 0,
+      "description": "",
+      "isAuditEnabled": true,
+      "resources": {
+        "config": {
+          "values": [
+            "CONFIG"
+          ],
+          "isExcludes": false,
+          "isRecursive": false
+        }
+      },
+      "policyItems": [
+        {
+          "accesses": [
+            {
+              "type": "read",
+              "isAllowed": true
+            },
+            {
+              "type": "write",
+              "isAllowed": true
+            }
+          ],
+          "users": [
+            "alice"
+          ],
+          "groups": [],
+          "roles": [],
+          "conditions": [],
+          "delegateAdmin": false
+        }
+      ],
+      "denyPolicyItems": [],
+      "allowExceptions": [],
+      "denyExceptions": [],
+      "dataMaskPolicyItems": [],
+      "rowFilterPolicyItems": [],
+      "serviceType": "druid",
+      "options": {},
+      "validitySchedules": [],
+      "policyLabels": [],
+      "zoneName": "",
+      "isDenyAllElse": false,
+      "id": 63,
+      "guid": "27725030-4a53-46a7-b58e-0d39763c019d",
+      "isEnabled": true,
+      "version": 1
+    },
+    {
+      "service": "cl1_druid",
+      "name": "alice-state",
+      "policyType": 0,
+      "policyPriority": 0,
+      "description": "",
+      "isAuditEnabled": true,
+      "resources": {
+        "state": {
+          "values": [
+            "STATE"
+          ],
+          "isExcludes": false,
+          "isRecursive": false
+        }
+      },
+      "policyItems": [
+        {
+          "accesses": [
+            {
+              "type": "read",
+              "isAllowed": true
+            },
+            {
+              "type": "write",
+              "isAllowed": true
+            }
+          ],
+          "users": [
+            "alice"
+          ],
+          "groups": [],
+          "roles": [],
+          "conditions": [],
+          "delegateAdmin": false
+        }
+      ],
+      "denyPolicyItems": [],
+      "allowExceptions": [],
+      "denyExceptions": [],
+      "dataMaskPolicyItems": [],
+      "rowFilterPolicyItems": [],
+      "serviceType": "druid",
+      "options": {},
+      "validitySchedules": [],
+      "policyLabels": [],
+      "zoneName": "",
+      "isDenyAllElse": false,
+      "id": 64,
+      "guid": "bddd74af-b505-452d-9930-c20971337f48",
+      "isEnabled": true,
+      "version": 1
+    }
+  ],
+  "startIndex": 0,
+  "pageSize": 0,
+  "totalCount": 0,
+  "resultSize": 0,
+  "queryTimeMS": 1585396899372,
+  "serviceDef": {
+    "id": 18,
+    "name": "druid",
+    "implClass": "org.apache.ranger.service.druid.RangerDruidService",
+    "label": "Druid",
+    "description": "Apache Druid",
+    "resources": [
+      {
+        "itemId": 10,
+        "name": "datasource",
+        "type": "string",
+        "level": 10,
+        "parent": "",
+        "mandatory": true,
+        "lookupSupported": true,
+        "recursiveSupported": false,
+        "excludesSupported": true,
+        "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+        "matcherOptions": {
+          "wildCard": true,
+          "ignoreCase": true
+        },
+        "validationRegEx": "",
+        "validationMessage": "",
+        "uiHint": "",
+        "label": "Datasource",
+        "description": "Druid Datasource"
+      },
+      {
+        "itemId": 20,
+        "name": "config",
+        "type": "string",
+        "level": 10,
+        "parent": "",
+        "mandatory": true,
+        "lookupSupported": true,
+        "recursiveSupported": false,
+        "excludesSupported": true,
+        "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+        "matcherOptions": {
+          "wildCard": true,
+          "ignoreCase": true
+        },
+        "validationRegEx": "",
+        "validationMessage": "",
+        "uiHint": "",
+        "label": "Config",
+        "description": "Druid Config"
+      },
+      {
+        "itemId": 30,
+        "name": "state",
+        "type": "string",
+        "level": 10,
+        "parent": "",
+        "mandatory": true,
+        "lookupSupported": true,
+        "recursiveSupported": false,
+        "excludesSupported": true,
+        "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+        "matcherOptions": {
+          "wildCard": true,
+          "ignoreCase": true
+        },
+        "validationRegEx": "",
+        "validationMessage": "",
+        "uiHint": "",
+        "label": "State",
+        "description": "Druid State"
+      }
+    ],
+    "accessTypes": [
+      {
+        "itemId": 1,
+        "name": "read",
+        "label": "Read"
+      },
+      {
+        "itemId": 2,
+        "name": "write",
+        "label": "Write"
+      }
+    ],
+    "configs": [
+      {
+        "itemId": 1,
+        "name": "username",
+        "type": "string",
+        "mandatory": true,
+        "label": "Username"
+      },
+      {
+        "itemId": 2,
+        "name": "password",
+        "type": "password",
+        "mandatory": true,
+        "label": "Password"
+      },
+      {
+        "itemId": 3,
+        "name": "druid.broker.url",
+        "type": "string",
+        "mandatory": true,
+        "defaultValue": "http://localhost:8082",
+        "label": "Druid broker host:port"
+      }
+    ],
+    "enums": [
+    ],
+    "contextEnrichers": [
+    ],
+    "policyConditions": [
+      {
+        "itemId": 1,
+        "name": "ip-range",
+        "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerIpMatcher",
+        "evaluatorOptions": {
+        },
+        "validationRegEx": "",
+        "validationMessage": "",
+        "uiHint": "",
+        "label": "IP Address Range",
+        "description": "IP Address Range"
+      }
+    ]
+  }
+}
diff --git a/extensions-core/druid-ranger-security/src/test/resources/ranger-druid-security.xml b/extensions-core/druid-ranger-security/src/test/resources/ranger-druid-security.xml
new file mode 100644
index 0000000..8698139
--- /dev/null
+++ b/extensions-core/druid-ranger-security/src/test/resources/ranger-druid-security.xml
@@ -0,0 +1,52 @@
+<?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.druid.service.name</name>
+        <value>cl1_druid</value>
+        <description>
+            Name of the Ranger service containing policies for this SampleApp instance
+        </description>
+    </property>
+
+    <property>
+        <name>ranger.plugin.druid.policy.source.impl</name>
+        <value>org.apache.druid.security.ranger.authorizer.RangerAdminClientImpl</value>
+        <description>
+            Policy source.
+        </description>
+    </property>
+
+    <property>
+        <name>ranger.plugin.druid.policy.pollIntervalMs</name>
+        <value>30000</value>
+        <description>
+            How often to poll for changes in policies?
+        </description>
+    </property>
+
+    <property>
+        <name>ranger.plugin.druid.policy.cache.dir</name>
+        <value>${project.build.directory}</value>
+        <description>
+            Directory where Ranger policies are cached after successful retrieval from the source
+        </description>
+    </property>
+
+</configuration>
diff --git a/licenses.yaml b/licenses.yaml
index bcdaa8c..ad81dc4 100644
--- a/licenses.yaml
+++ b/licenses.yaml
@@ -4222,6 +4222,238 @@ libraries:
 
 ---
 
+name: org.apache.ranger ranger-plugins-audit
+license_category: binary
+version: 2.0.0
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.apache.ranger: ranger-plugins-audit
+
+---
+
+name: org.apache.ranger ranger-plugins-common
+license_category: binary
+version: 2.0.0
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.apache.ranger: ranger-plugins-common
+
+---
+
+name: com.101tec zkclient
+license_category: binary
+version: '0.10'
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - com.101tec: zkclient
+
+---
+
+name: com.kstruct gethostname4j
+license_category: binary
+version: 0.0.2
+module: druid-ranger-security
+license_name: MIT License
+libraries:
+  - com.kstruct: gethostname4j
+
+---
+
+name: com.sun.jersey jersey-bundle
+license_category: binary
+version: 1.19.3
+module: druid-ranger-security
+license_name: CDDL 1.1
+libraries:
+  - com.sun.jersey: jersey-bundle
+
+---
+
+name: net.java.dev.jna jna-platform
+license_category: binary
+version: 5.2.0
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - net.java.dev.jna: jna-platform
+
+---
+
+name: JOpt Simple
+license_category: binary
+version: 5.0.4
+module: druid-ranger-security
+license_name: MIT License
+libraries:
+  - net.sf.jopt-simple: jopt-simple
+copyright: Paul R. Holser, Jr.
+
+---
+
+name: org.apache.httpcomponents httpmime
+license_category: binary
+version: 4.5.3
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.apache.httpcomponents: httpmime
+
+---
+
+name: Apache Kafka
+license_category: binary
+version: 2.0.0
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.apache.kafka: kafka-clients
+notices:
+  - kafka-clients: 'Apache Kafka Copyright 2019 The Apache Software Foundation.
+
+This distribution has a binary dependency on jersey, which is available under
+the CDDL License. The source code of jersey can be found at https://github.com/jersey/jersey/.'
+
+---
+
+name: org.apache.kafka kafka_2.11
+license_category: binary
+version: 2.0.0
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.apache.kafka: kafka_2.11
+
+---
+
+name: org.apache.ranger ranger-plugins-cred
+license_category: binary
+version: 2.0.0
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.apache.ranger: ranger-plugins-cred
+
+---
+
+name: org.apache.solr solr-solrj
+license_category: binary
+version: 7.7.1
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.apache.solr: solr-solrj
+
+---
+
+name: org.codehaus.woodstox stax2-api
+license_category: binary
+version: 3.1.4
+module: druid-ranger-security
+license_name: BSD-3-Clause License
+libraries:
+  - org.codehaus.woodstox: stax2-api
+
+---
+
+name: org.codehaus.woodstox woodstox-core-asl
+license_category: binary
+version: 4.4.1
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.codehaus.woodstox: woodstox-core-asl
+
+---
+
+name: org.eclipse.persistence commonj.sdo
+license_category: binary
+version: 2.1.1
+module: druid-ranger-security
+license_name: Eclipse Distribution License 1.0
+libraries:
+  - org.eclipse.persistence: commonj.sdo
+
+---
+
+name: org.eclipse.persistence eclipselink
+license_category: binary
+version: 2.5.2
+module: druid-ranger-security
+license_name: Eclipse Distribution License 1.0
+libraries:
+  - org.eclipse.persistence: eclipselink
+
+---
+
+name: org.eclipse.persistence javax.persistence
+license_category: binary
+version: 2.1.0
+module: druid-ranger-security
+license_name: Eclipse Distribution License 1.0
+libraries:
+  - org.eclipse.persistence: javax.persistence
+
+---
+
+name: org.noggit noggit
+license_category: binary
+version: '0.8'
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.noggit: noggit
+
+---
+
+name: Scala Library
+license_category: binary
+version: 2.11.12
+module: druid-ranger-security
+license_name: BSD-3-Clause License
+libraries:
+  - org.scala-lang: scala-library
+copyright: LAMP/EPFL and Lightbend, Inc.
+
+---
+
+name: org.scala-lang scala-reflect
+license_category: binary
+version: 2.11.12
+module: druid-ranger-security
+license_name: BSD-3-Clause License
+libraries:
+  - org.scala-lang: scala-reflect
+
+---
+
+name: snappy-java
+license_category: binary
+version: 1.1.7.1
+module: druid-ranger-security
+license_name: Apache License version 2.0
+libraries:
+  - org.xerial.snappy: snappy-java
+notices:
+  - snappy-java: |
+      This product includes software developed by Google
+       Snappy: http://code.google.com/p/snappy/ (New BSD License)
+
+
+      This library containd statically linked libstdc++. This inclusion is allowed by
+      "GCC RUntime Library Exception"
+      http://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html
+
+      == Contributors ==
+        * Tatu Saloranta
+          * Providing benchmark suite
+        * Alec Wysoker
+          * Performance and memory usage improvement
+
+---
+
 # Web console modules start
 name: "@babel/runtime"
 license_category: binary
diff --git a/pom.xml b/pom.xml
index 6e43316..0305e87 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,6 +79,8 @@
         <apache.curator.version>4.1.0</apache.curator.version>
         <apache.curator.test.version>2.12.0</apache.curator.test.version>
         <apache.kafka.version>2.2.2</apache.kafka.version>
+        <apache.ranger.version>2.0.0</apache.ranger.version>
+        <apache.ranger.gson.version>2.2.4</apache.ranger.gson.version>
         <avatica.version>1.15.0</avatica.version>
         <avro.version>1.9.2</avro.version>
         <calcite.version>1.21.0</calcite.version>
@@ -162,6 +164,7 @@
         <module>extensions-core/simple-client-sslcontext</module>
         <module>extensions-core/druid-basic-security</module>
         <module>extensions-core/google-extensions</module>
+        <module>extensions-core/druid-ranger-security</module>
         <!-- Community extensions -->
         <module>extensions-contrib/influx-extensions</module>
         <module>extensions-contrib/cassandra-storage</module>
diff --git a/website/.spelling b/website/.spelling
index 26aac1c..b3f1dea 100644
--- a/website/.spelling
+++ b/website/.spelling
@@ -1722,4 +1722,8 @@ isRobot
 isUnpatrolled
 metroCode
 regionIsoCode
-regionName
\ No newline at end of file
+regionName
+ - ../docs/development/extensions-core/druid-ranger-security.md
+json
+metastore
+UserGroupInformation
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org