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