You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by es...@apache.org on 2017/02/03 09:00:32 UTC
[30/50] [abbrv] incubator-hawq git commit: HAWQ-1203. Ranger Plugin
Service Implementation. (with contributions by Lav Jain and Leslie Chang)
(close #1092)
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/pom.xml b/ranger-plugin/pom.xml
new file mode 100644
index 0000000..20d3112
--- /dev/null
+++ b/ranger-plugin/pom.xml
@@ -0,0 +1,248 @@
+<?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.hawq</groupId>
+ <artifactId>ranger-plugin</artifactId>
+ <version>2.1.0.0</version>
+ <packaging>pom</packaging>
+ <name>HAWQ Ranger Plugin</name>
+ <description>HAWQ Ranger Plugin</description>
+
+ <modules>
+ <module>admin-plugin</module>
+ <module>service</module>
+ </modules>
+
+ <properties>
+ <jackson.version>1.9</jackson.version>
+ <release.version>1</release.version>
+ <postgresql.version>9.1-901-1.jdbc4</postgresql.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rpm-maven-plugin</artifactId>
+ <version>2.0.1</version>
+ <inherited>false</inherited>
+ <executions>
+ <execution>
+ <inherited>false</inherited>
+ <phase>install</phase>
+ <goals>
+ <goal>rpm</goal>
+ </goals>
+ </execution>
+ </executions>
+
+ <configuration>
+ <copyright>ASL 2.0</copyright>
+ <group>org.apache.hawq.ranger</group>
+ <defaultUsername>gpadmin</defaultUsername>
+ <defaultGroupname>gpadmin</defaultGroupname>
+ <description>
+ HAWQ Ranger plugin.
+ </description>
+ <release>${release.version}</release>
+ <requires>
+ <require>bigtop-tomcat</require>
+ <require>hawq_${hawq.name.version} >= ${project.version}</require>
+ </requires>
+ <mappings>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/bin</directory>
+ <filemode>755</filemode>
+ <sources>
+ <source>
+ <location>scripts</location>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/lib</directory>
+ <sources>
+ <source>
+ <location>admin-plugin/target/ranger-plugin-admin-${project.version}.jar</location>
+ </source>
+ <source>
+ <location>admin-plugin/target/lib/postgresql-${postgresql.version}.jar</location>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/etc</directory>
+ <sources>
+ <source>
+ <location>conf/ranger-servicedef-hawq.json</location>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/bin</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/logs</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/temp</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/work</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/webapps</directory>
+ <sources>
+ <source>
+ <location>service/target/ranger-plugin-service-${project.version}.war</location>
+ <destination>rps.war</destination>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/conf</directory>
+ <sources>
+ <source>
+ <location>conf/tomcat-server.xml</location>
+ </source>
+ </sources>
+ </mapping>
+ </mappings>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.7</version>
+ <executions>
+ <execution>
+ <id>regex-property</id>
+ <goals>
+ <goal>regex-property</goal>
+ </goals>
+ <configuration>
+ <name>hawq.name.version</name>
+ <value>${project.version}</value>
+ <regex>^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)?$</regex>
+ <replacement>$1_$2_$3_$4</replacement>
+ <failIfNoMatch>true</failIfNoMatch>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ <version>0.6.0</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>${postgresql.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-xc</artifactId>
+ <version>1.9.13</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>11.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.10.19</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.6.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.6.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/scripts/register_hawq.sh
----------------------------------------------------------------------
diff --git a/ranger-plugin/scripts/register_hawq.sh b/ranger-plugin/scripts/register_hawq.sh
new file mode 100755
index 0000000..11e2df8
--- /dev/null
+++ b/ranger-plugin/scripts/register_hawq.sh
@@ -0,0 +1,217 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+function usage() {
+ echo "USAGE: register_hawq.sh -r ranger_host:ranger_port -u ranger_user -p ranger_password -h hawq_host:hawq_port -w hawq_user -q hawq_password"
+ exit 1
+}
+
+function fail() {
+ echo "ERROR: $1"
+ exit 1
+}
+
+function mask() {
+ printf -v stars '%*s' ${#1} ''
+ echo "[${stars// /*}]"
+}
+
+function read_value() {
+ local input
+ read -p "Enter value for $1 : " input
+ echo $input
+}
+
+function read_password() {
+ local input
+ read -s -p "Enter value for $1 : " input
+ echo $input
+}
+
+function get_ranger_url() {
+ while [[ -z "$RANGER_URL" ]]
+ do
+ RANGER_URL=$(read_value "Ranger Admin host and port (e.g. abc.com:6080)")
+ done
+ local prefix="http://"
+ RANGER_URL=${RANGER_URL#$prefix}
+}
+
+function get_ranger_user() {
+ while [[ -z "$RANGER_USER" ]]
+ do
+ RANGER_USER=$(read_value "Ranger Admin user name")
+ done
+}
+
+function get_ranger_password() {
+ while [[ -z "$RANGER_PASSWORD" ]]
+ do
+ RANGER_PASSWORD=$(read_password "Ranger Admin password")
+ echo
+ done
+}
+
+function get_hawq_url() {
+ #todo read hawq-site.xml ?
+ local default=`hostname -f`
+ default="${default}:5432"
+ while [[ -z "$HAWQ_URL" ]]
+ do
+ HAWQ_URL=$(read_value "HAWQ Master host and port [${default}]")
+ done
+ local prefix="http://"
+ HAWQ_URL=${HAWQ_URL#$prefix}
+ local parts=(${HAWQ_URL//:/ })
+ if [ ${#parts[@]} != 2 ]; then
+ fail "Incorrect value for HAWQ Master host and port."
+ fi
+ HAWQ_HOST=${parts[0]}
+ HAWQ_PORT=${parts[1]}
+}
+
+function get_hawq_user() {
+ local default="gpadmin"
+ while [[ -z "$HAWQ_USER" ]]
+ do
+ HAWQ_USER=$(read_value "HAWQ user name [${default}]")
+ done
+}
+
+function get_hawq_password() {
+ while [[ -z "$HAWQ_PASSWORD" ]]
+ do
+ HAWQ_PASSWORD=$(read_password "HAWQ password")
+ echo
+ done
+}
+
+function parse_params() {
+ while [[ $# -gt 0 ]]
+ do
+ key="$1"
+ case $key in
+ -r)
+ RANGER_URL="$2"
+ shift
+ ;;
+ -u)
+ RANGER_USER="$2"
+ shift
+ ;;
+ -p)
+ RANGER_PASSWORD="$2"
+ shift
+ ;;
+ -h)
+ HAWQ_URL="$2"
+ shift
+ ;;
+ -w)
+ HAWQ_USER="$2"
+ shift
+ ;;
+ -q)
+ HAWQ_PASSWORD="$2"
+ shift
+ ;;
+ *)
+ usage
+ ;;
+ esac
+ shift
+ done
+}
+
+function validate_params() {
+ get_ranger_url
+ get_ranger_user
+ get_ranger_password
+ get_hawq_url
+ get_hawq_user
+ get_hawq_password
+ echo "RANGER URL = ${RANGER_URL}"
+ echo "RANGER User = ${RANGER_USER}"
+ echo "RANGER Password = $(mask ${RANGER_PASSWORD})"
+ echo "HAWQ HOST = ${HAWQ_HOST}"
+ echo "HAWQ PORT = ${HAWQ_PORT}"
+ echo "HAWQ User = ${HAWQ_USER}"
+ echo "HAWQ Password = $(mask ${HAWQ_PASSWORD})"
+}
+
+function check_hawq_service_definition() {
+ echo $(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} http://${RANGER_URL}/service/public/v2/api/servicedef/name/hawq | grep hawq | wc -l)
+}
+
+function create_hawq_service_definition() {
+ if [ $(check_hawq_service_definition) == 0 ]; then
+ local json_file="$(dirname ${SCRIPT_DIR})/etc/ranger-servicedef-hawq.json"
+ if [ ! -f ${json_file} ]; then
+ fail "File ${json_file} not found."
+ fi
+ echo "HAWQ service definition was not found in Ranger Admin, creating it by uploading ${json_file}"
+ local output=$(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} -H "Content-Type: application/json" -X POST http://${RANGER_URL}/service/plugins/definitions -d @${json_file})
+ local created=$(echo ${output} | grep created | wc -l)
+ if [ ${created} == 0 ] || [ $(check_hawq_service_definition) == 0 ]; then
+ fail "Creation of HAWQ service definition from ${json_file} in Ranger Admin at ${RANGER_URL} failed. ${output}"
+ fi
+ else
+ echo "HAWQ service definition already exists in Ranger Admin, nothing to do."
+ fi
+}
+
+function check_hawq_service_instance() {
+ echo $(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} http://${RANGER_URL}/service/public/v2/api/service/name/hawq | grep hawq | wc -l)
+}
+
+function create_hawq_service_instance() {
+ if [ $(check_hawq_service_instance) == 0 ]; then
+ local payload="{\"name\":\"hawq\",
+ \"type\":\"hawq\",
+ \"description\":\"HAWQ Master\",
+ \"isEnabled\":true,
+ \"configs\":{\"username\":\"${HAWQ_USER}\",
+ \"password\":\"${HAWQ_PASSWORD}\",
+ \"hostname\":\"${HAWQ_HOST}\",
+ \"port\":\"${HAWQ_PORT}\"}}"
+
+ echo "HAWQ service instance was not found in Ranger Admin, creating it."
+ local output=$(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} -H "Content-Type: application/json" -X POST http://${RANGER_URL}/service/public/v2/api/service -d "${payload}")
+ local created=$(echo ${output} | grep created | wc -l)
+ if [ ${created} == 0 ] || [ $(check_hawq_service_instance) == 0 ]; then
+ fail "Creation of HAWQ service instance in Ranger Admin at ${RANGER_URL} failed. ${output}"
+ fi
+ else
+ echo "HAWQ service instance already exists in Ranger Admin, nothing to do."
+ fi
+}
+
+main() {
+ if [[ $# -lt 1 ]]; then
+ usage
+ fi
+ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+ parse_params "$@"
+ validate_params
+ create_hawq_service_definition
+ create_hawq_service_instance
+}
+main "$@"
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/scripts/rps.sh
----------------------------------------------------------------------
diff --git a/ranger-plugin/scripts/rps.sh b/ranger-plugin/scripts/rps.sh
new file mode 100755
index 0000000..e8ccf3a
--- /dev/null
+++ b/ranger-plugin/scripts/rps.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+if [ $# -le 0 ]; then
+ echo "Usage: rps (start|stop|init) [<catalina-args...>]"
+ exit 1
+fi
+
+actionCmd=$1
+shift
+
+CWDIR=$( cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
+source $CWDIR/rps_env.sh
+
+setup_rps() {
+ echo "Initializing Hawq Ranger Plugin Service..."
+ cp $CATALINA_HOME/conf.template/* $CATALINA_BASE/conf
+ cp $CATALINA_BASE/conf/tomcat-server.xml $CATALINA_BASE/conf/server.xml
+ pushd $CATALINA_BASE/webapps >/dev/null
+ unzip -d rps rps.war >/dev/null
+ find . -name ranger-hawq-security.xml | xargs sed -i \
+ "s/localhost:6080/$RANGER_ADMIN_HOST:$RANGER_ADMIN_PORT/g"
+ popd >/dev/null
+ echo "Hawq Ranger Plugin Service installed on http://$RPS_HOST:$RPS_PORT/rps"
+ echo "Please use 'rps.sh start' to start the service"
+}
+
+case $actionCmd in
+ (init)
+ setup_rps
+ ;;
+ (start)
+ $CATALINA_HOME/bin/catalina.sh start "$@"
+ echo "Waiting for RPS service to start..."
+ sleep 15
+ ;;
+ (stop)
+ $CATALINA_HOME/bin/catalina.sh stop "$@"
+ echo "Waiting for RPS service to stop..."
+ sleep 10
+ ;;
+esac
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/scripts/rps_env.sh
----------------------------------------------------------------------
diff --git a/ranger-plugin/scripts/rps_env.sh b/ranger-plugin/scripts/rps_env.sh
new file mode 100755
index 0000000..ae36e8f
--- /dev/null
+++ b/ranger-plugin/scripts/rps_env.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+export CATALINA_HOME=/usr/lib/bigtop-tomcat
+export CATALINA_BASE=/usr/local/hawq/ranger/plugin-service
+
+export RANGER_ADMIN_HOST=${RANGER_ADMIN_HOST:-localhost}
+export RANGER_ADMIN_PORT=${RANGER_ADMIN_PORT:-6080}
+
+export RPS_HOST=${RPS_HOST:-localhost}
+export RPS_PORT=${RPS_PORT:-8432}
+export CATALINA_OPTS="-Dhttp.host=$RPS_HOST -Dhttp.port=$RPS_PORT"
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/pom.xml b/ranger-plugin/service/pom.xml
new file mode 100644
index 0000000..3f2f9f8
--- /dev/null
+++ b/ranger-plugin/service/pom.xml
@@ -0,0 +1,88 @@
+<?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.hawq</groupId>
+ <artifactId>ranger-plugin-service</artifactId>
+ <packaging>war</packaging>
+ <name>HAWQ Ranger Service</name>
+ <description>HAWQ Ranger Service</description>
+ <parent>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin</artifactId>
+ <version>2.1.0.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <!-- use mvn tomcat6:run-war to run the appserver with the app deployed -->
+ <groupId>org.apache.tomcat.maven</groupId>
+ <artifactId>tomcat6-maven-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <path>/rps</path>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-xc</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </dependency>
+ </dependencies>
+
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java
new file mode 100644
index 0000000..625ce50
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+
+/**
+ * Interface for making authorization decisions.
+ */
+public interface HawqAuthorizer {
+
+ /**
+ * Determines whether access should be allowed for the given authorization request.
+ * @param request authorization request
+ * @return authorization response
+ */
+ AuthorizationResponse isAccessAllowed(AuthorizationRequest request);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java
new file mode 100644
index 0000000..04d6f99
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java
@@ -0,0 +1,263 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+import org.apache.hawq.ranger.authorization.model.HawqPrivilege;
+import org.apache.hawq.ranger.authorization.model.HawqResource;
+import org.apache.hawq.ranger.authorization.model.ResourceAccess;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.hawq.ranger.authorization.Utils.HAWQ;
+
+/**
+ * Authorizer implementation that uses Ranger to make access decision. Implemented as a singleton.
+ */
+public class RangerHawqAuthorizer implements HawqAuthorizer {
+
+ private static final Log LOG = LogFactory.getLog(RangerHawqAuthorizer.class);
+
+ private static final RangerHawqAuthorizer INSTANCE = new RangerHawqAuthorizer();
+
+ private RangerBasePlugin rangerPlugin;
+
+ /**
+ * Returns the instance of the RangerHawqAuthorizer.
+ * @return the singleton instance
+ */
+ public static RangerHawqAuthorizer getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Constructor. Initializes Ranger Base Plugin to fetch policies from Ranger.
+ */
+ private RangerHawqAuthorizer() {
+
+ LOG.info("Initializing RangerHawqAuthorizer");
+
+ String appId = Utils.getAppId();
+
+ LOG.info(String.format("Initializing RangerBasePlugin for service %s:%s", HAWQ, appId));
+ rangerPlugin = new RangerBasePlugin(HAWQ, appId);
+ rangerPlugin.init();
+ LOG.info(String.format("Initialized RangerBasePlugin for service %s:%s", HAWQ, appId));
+ }
+
+ @Override
+ public AuthorizationResponse isAccessAllowed(AuthorizationRequest request) {
+
+ // validate request to make sure no data is missing
+ validateRequest(request);
+
+ // prepare response object
+ AuthorizationResponse response = new AuthorizationResponse();
+ response.setRequestId(request.getRequestId());
+ Set<ResourceAccess> access = new HashSet<>();
+ response.setAccess(access);
+
+ // iterate over resource requests, augment processed ones with the decision and add to the response
+ for (ResourceAccess resourceAccess : request.getAccess()) {
+ boolean accessAllowed = authorizeResource(resourceAccess, request.getUser());
+ resourceAccess.setAllowed(accessAllowed);
+ access.add(resourceAccess);
+ }
+
+ return response;
+ }
+
+ /**
+ * Authorizes access to a single resource for a given user.
+ *
+ * @param resourceAccess resource to authorize access to
+ * @param user user requesting authorization
+ * @return true if access is authorized, false otherwise
+ */
+ private boolean authorizeResource(ResourceAccess resourceAccess, String user) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("Request: access for user=%s to resource=%s with privileges=%s",
+ user, resourceAccess.getResource(), resourceAccess.getPrivileges()));
+ }
+
+ RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl();
+ //resource.setOwnerUser();
+ for (Map.Entry<HawqResource, String> resourceEntry : resourceAccess.getResource().entrySet()) {
+ rangerResource.setValue(resourceEntry.getKey().name(), resourceEntry.getValue());
+ }
+
+ boolean accessAllowed = true;
+ // iterate over all privileges requested
+ for (HawqPrivilege privilege : resourceAccess.getPrivileges()) {
+ // TODO not clear how we will get user groups -- Kerberos case ?
+ Set<String> userGroups = Collections.emptySet();
+ boolean privilegeAuthorized = authorizeResourcePrivilege(rangerResource, privilege.name(), user, userGroups);
+ // ALL model of evaluation -- all privileges must be authorized for access to be allowed
+ if (!privilegeAuthorized) {
+ accessAllowed = false;
+ break; // terminate early if even a single privilege is not authorized
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("Decision: accessAllowed=%s for user=%s to resource=%s with privileges=%s",
+ accessAllowed, user, resourceAccess.getResource(), resourceAccess.getPrivileges()));
+ }
+
+ return accessAllowed;
+ }
+
+ /**
+ * Authorizes access of a given type (privilege) to a single resource for a given user.
+ *
+ * @param rangerResource resource to authorize access to
+ * @param accessType privilege requested for a given resource
+ * @param user user requesting authorization
+ * @param userGroups groups a user belongs to
+ * @return true if access is authorized, false otherwise
+ */
+ private boolean authorizeResourcePrivilege(RangerAccessResource rangerResource, String accessType, String user, Set<String> userGroups) {
+
+ Map<String, String> resourceMap = rangerResource.getAsMap();
+ String database = resourceMap.get(HawqResource.database.name());
+ String schema = resourceMap.get(HawqResource.schema.name());
+ int resourceSize = resourceMap.size();
+
+ // special handling for non-leaf policies
+ if (accessType.equals(HawqPrivilege.create.name()) && database != null && schema == null && resourceSize == 1) {
+ accessType = HawqPrivilege.create_schema.toValue();
+ LOG.debug("accessType mapped to: create-schema");
+ } else if (accessType.equals(HawqPrivilege.usage.name()) && database != null && schema != null && resourceSize == 2) {
+ accessType = HawqPrivilege.usage_schema.toValue();
+ LOG.debug("accessType mapped to: usage-schema");
+ }
+
+ RangerAccessRequest rangerRequest = new RangerAccessRequestImpl(rangerResource, accessType, user, userGroups);
+ RangerAccessResult result = rangerPlugin.isAccessAllowed(rangerRequest);
+ boolean accessAllowed = result != null && result.getIsAllowed();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("--- RangerDecision: accessAllowed=%s for user=%s to resource=%s with privileges=%s, result present=%s",
+ accessAllowed, user, rangerResource.getAsString(), accessType, result!=null));
+ }
+
+ return accessAllowed;
+ }
+
+ /**
+ * Validates that authorization requests do not have any missing data.
+ *
+ * @param request authorization request
+ * @throws IllegalArgumentException if any data is missing
+ */
+ private void validateRequest(AuthorizationRequest request) {
+ LOG.debug("Validating authorization request");
+
+ if (request == null) {
+ throw new IllegalArgumentException("request is null");
+ }
+
+ if (request.getRequestId() == null) {
+ throw new IllegalArgumentException("requestId field is missing or null in the request");
+ }
+
+ if (StringUtils.isEmpty(request.getUser())) {
+ throw new IllegalArgumentException("user field is missing or empty in the request");
+ }
+
+ if (StringUtils.isEmpty(request.getClientIp())) {
+ throw new IllegalArgumentException("clientIp field is missing or empty in the request");
+ }
+
+ if (StringUtils.isEmpty(request.getContext())) {
+ throw new IllegalArgumentException("context field is missing or empty in the request");
+ }
+
+ Set<ResourceAccess> accessSet = request.getAccess();
+ if (CollectionUtils.isEmpty(accessSet)) {
+ throw new IllegalArgumentException("access field is missing or empty in the request");
+ }
+
+ for (ResourceAccess access : accessSet) {
+ validateResourceAccess(access);
+ }
+
+ LOG.debug("Successfully validated authorization request");
+ }
+
+ /**
+ * Validates that resource access does not have any missing data.
+ *
+ * @param access resource access data
+ * @throws IllegalArgumentException if any data is missing
+ */
+ private void validateResourceAccess(ResourceAccess access) {
+ Map<HawqResource, String> resourceMap = access.getResource();
+ if (MapUtils.isEmpty(resourceMap)) {
+ throw new IllegalArgumentException("resource field is missing or empty in the request");
+ }
+ for (Map.Entry<HawqResource, String> resourceEntry : resourceMap.entrySet()) {
+ if (StringUtils.isEmpty(resourceEntry.getValue())) {
+ throw new IllegalArgumentException(
+ String.format("resource value is missing for key=%s in the request", resourceEntry.getKey())
+ );
+ }
+ }
+ if (CollectionUtils.isEmpty(access.getPrivileges())) {
+ throw new IllegalArgumentException("set of privileges is missing empty in the request");
+ }
+ }
+
+
+
+ /**
+ * Sets an instance of the Ranger Plugin for testing.
+ *
+ * @param plugin plugin instance to use while testing
+ */
+ void setRangerPlugin(RangerBasePlugin plugin) {
+ rangerPlugin = plugin;
+ }
+
+ /**
+ * Returns the instance of the Ranger Plugin for testing.
+ *
+ * @return BaseRangerPlugin instance
+ */
+ RangerBasePlugin getRangerPlugin() {
+ return rangerPlugin;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java
new file mode 100644
index 0000000..26a7660
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hawq.ranger.authorization;
+
+import com.sun.jersey.spi.resource.Singleton;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.Date;
+
+/**
+ * JAX-RS resource for the authorization endpoint.
+ */
+@Path("/")
+@Singleton
+public class RangerHawqPluginResource {
+
+ private static final Log LOG = LogFactory.getLog(RangerHawqPluginResource.class);
+
+ private HawqAuthorizer authorizer;
+ private String version;
+
+ /**
+ * Constructor. Creates a new instance of the resource that uses <code>RangerHawqAuthorizer</code>.
+ */
+ public RangerHawqPluginResource() {
+ this.authorizer = RangerHawqAuthorizer.getInstance();
+ }
+
+
+ @Path("/version")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response version()
+ {
+ String output = "{\"version\":\"" + Utils.getVersion() + "\"}";
+ return Response.status(200).entity(output).build();
+ }
+
+ /**
+ * Authorizes a request to access protected resources with requested privileges.
+ * @param request authorization request
+ * @return authorization response
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public AuthorizationResponse authorize(AuthorizationRequest request)
+ {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Received authorization request: " + request);
+ }
+
+ // exceptions are handled by ServiceExceptionMapper
+ AuthorizationResponse response = authorizer.isAccessAllowed(request);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Returning authorization response: " + response);
+ }
+ return response;
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java
new file mode 100644
index 0000000..b983d72
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hawq.ranger.authorization;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Maps service exceptions to HTTP response.
+ */
+@Provider
+public class ServiceExceptionMapper implements ExceptionMapper<Throwable> {
+
+ private static final Log LOG = LogFactory.getLog(ServiceExceptionMapper.class);
+
+ @Override
+ public Response toResponse(Throwable e) {
+
+ LOG.error("Service threw an exception: ", e);
+
+ // default to internal server error (HTTP 500)
+ Response.Status status = Response.Status.INTERNAL_SERVER_ERROR;
+
+ if (e instanceof IllegalArgumentException) {
+ status = Response.Status.BAD_REQUEST;
+ }
+
+ ErrorPayload error = new ErrorPayload(status.getStatusCode(), e.getMessage());
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("Returning error response: status=%s message=%s",
+ error.getStatus(), error.getMessage()));
+ }
+
+ return Response.status(status)
+ .entity(error)
+ .type(MediaType.APPLICATION_JSON)
+ .build();
+ }
+
+ /**
+ * Represents payload to be serialized as JSON into response.
+ */
+ public static class ErrorPayload {
+ private int status;
+ private String message;
+
+ /**
+ * Constructor.
+ * @param status HTTP error status
+ * @param message error message
+ */
+ public ErrorPayload(int status, String message) {
+ this.status = status;
+ this.message = message;
+ }
+
+ /**
+ * Returns status code
+ * @return status code
+ */
+ public int getStatus() {
+ return status;
+ }
+
+ /**
+ * Returns error message
+ * @return error message
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java
new file mode 100644
index 0000000..86f7fc4
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java
@@ -0,0 +1,80 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Utility class for reading values from the property file.
+ */
+public abstract class Utils {
+
+ public static final String HAWQ = "hawq";
+ public static final String UNKNOWN = "unknown";
+ public static final String APP_ID_PROPERTY = "ranger.hawq.instance";
+ public static final String VERSION_PROPERTY = "version";
+ public static final String RANGER_SERVICE_PROPERTY_FILE = "rps.properties";
+
+ private static final Log LOG = LogFactory.getLog(Utils.class);
+ private static final Properties properties = readPropertiesFromFile();
+
+ /**
+ * Retrieves the app id from the environment variable with the key ranger.hawq.instance
+ * or from the rps.properties file with the key ranger.hawq.instance
+ *
+ * If none exist, hawq is used as the default
+ *
+ * @return String id of the app
+ */
+ public static String getAppId() {
+ return System.getProperty(APP_ID_PROPERTY, properties.getProperty(APP_ID_PROPERTY, HAWQ));
+ }
+
+ /**
+ * Retrieves the version read from the property file.
+ *
+ * If none exist, unknown is used as the default
+ *
+ * @return version of the service
+ */
+ public static String getVersion() {
+ return properties.getProperty(VERSION_PROPERTY, UNKNOWN);
+ }
+
+ /**
+ * Reads properties from the property file.
+ * @return properties read from the file
+ */
+ private static Properties readPropertiesFromFile() {
+ Properties prop = new Properties();
+ InputStream inputStream = Utils.class.getClassLoader().getResourceAsStream(RANGER_SERVICE_PROPERTY_FILE);
+ try {
+ prop.load(inputStream);
+ } catch (IOException e) {
+ LOG.error("Failed to read from: " + RANGER_SERVICE_PROPERTY_FILE);
+ }
+ return prop;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java
new file mode 100644
index 0000000..6e8ab4f
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import java.util.Set;
+
+/**
+ * Model for submitting an authorization request for multiple resources.
+ */
+public class AuthorizationRequest {
+
+ private Integer requestId;
+ private String user;
+ private String clientIp;
+ private String context;
+ private Set<ResourceAccess> access;
+
+ /**
+ * Returns request id.
+ * @return id of the request
+ */
+ public Integer getRequestId() {
+ return requestId;
+ }
+
+ /**
+ * Sets request id.
+ * @param requestId id of the request
+ */
+ public void setRequestId(Integer requestId) {
+ this.requestId = requestId;
+ }
+
+ /**
+ * Returns user name for the user submitting the access request.
+ * @return name of the user
+ */
+ public String getUser() {
+ return user;
+ }
+
+ /**
+ * Sets user name for the user submitting the access request.
+ * @param user name of the user
+ */
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ /**
+ * Returns IP address of the client where the user request is made from.
+ * @return IP address of the user's client
+ */
+ public String getClientIp() {
+ return clientIp;
+ }
+
+ /**
+ * Sets IP address of the client where the user request is made from.
+ * @param clientIp IP address of the user's client
+ */
+ public void setClientIp(String clientIp) {
+ this.clientIp = clientIp;
+ }
+
+ /**
+ * Returns context of the request, usually a SQL query that the user ran
+ * @return context of the request
+ */
+ public String getContext() {
+ return context;
+ }
+
+ /**
+ * Sets the context of the request, usually a SQL query that the user ran
+ * @param context context of the request
+ */
+ public void setContext(String context) {
+ this.context = context;
+ }
+
+ /**
+ * Returns a set of <code>ResourceAccess</code> objects.
+ * @return s set of <code>ResourceAccess</code> objects
+ */
+ public Set<ResourceAccess> getAccess() {
+ return access;
+ }
+
+ /**
+ * Sets <code>ResourceAccess</code> objects
+ * @param access a set of <code>ResourceAccess</code> objects
+ */
+ public void setAccess(Set<ResourceAccess> access) {
+ this.access = access;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java
new file mode 100644
index 0000000..f989b8d
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java
@@ -0,0 +1,63 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import java.util.Set;
+
+/**
+ * Model for response containing authorization decisions for access to multiple resources.
+ */
+public class AuthorizationResponse {
+
+ private Integer requestId;
+ private Set<ResourceAccess> access;
+
+ /**
+ * Returns request id.
+ * @return id of the request
+ */
+ public Integer getRequestId() {
+ return requestId;
+ }
+
+ /**
+ * Sets request id.
+ * @param requestId id of the request
+ */
+ public void setRequestId(Integer requestId) {
+ this.requestId = requestId;
+ }
+
+ /**
+ * Returns a set of <code>ResourceAccess</code> objects.
+ * @return a set of <code>ResourceAccess</code> objects
+ */
+ public Set<ResourceAccess> getAccess() {
+ return access;
+ }
+
+ /**
+ * Sets <code>ResourceAccess</code> objects
+ * @param access a set of <code>ResourceAccess</code> objects
+ */
+ public void setAccess(Set<ResourceAccess> access) {
+ this.access = access;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java
new file mode 100644
index 0000000..ffce67a
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonValue;
+
+/**
+ * Model enumeration of types of HAWQ privileges.
+ */
+public enum HawqPrivilege {
+ select,
+ insert,
+ update,
+ delete,
+ references,
+ usage,
+ create,
+ connect,
+ execute,
+ temp,
+ create_schema,
+ usage_schema,
+ all;
+
+ /**
+ * Returns HawqPrivilege type by case-insensitive lookup of the value.
+ * @param key case insensitive string representation of the privilege
+ * @return instance of HawqPrivilege
+ */
+ @JsonCreator
+ public static HawqPrivilege fromString(String key) {
+ return key == null ? null : HawqPrivilege.valueOf(key.replace('-', '_').toLowerCase());
+ }
+
+ /**
+ * Returns string representation of the enum, replaces underscores with dashes.
+ * @return string representation of the enum
+ */
+ @JsonValue
+ public String toValue() {
+ return name().replace('_', '-');
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java
new file mode 100644
index 0000000..c9de4e7
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java
@@ -0,0 +1,46 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+
+/**
+ * Model enumeration of types of HAWQ resources.
+ */
+public enum HawqResource {
+ database,
+ schema,
+ table,
+ sequence,
+ function,
+ language,
+ tablespace,
+ protocol;
+
+ /**
+ * Returns HawqResource type by case-insensitive lookup of the value.
+ * @param key case insensitive string representation of the resource
+ * @return instance of HawqResource
+ */
+ @JsonCreator
+ public static HawqResource fromString(String key) {
+ return key == null ? null : HawqResource.valueOf(key.toLowerCase());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java
new file mode 100644
index 0000000..df1631a
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java
@@ -0,0 +1,85 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Model object for requesting access to a single resource.
+ */
+public class ResourceAccess {
+
+ private Map<HawqResource, String> resource;
+ private Set<HawqPrivilege> privileges;
+ private boolean allowed = false;
+
+ public Set<HawqPrivilege> getPrivileges() {
+ return privileges;
+ }
+
+ public void setPrivileges(Set<HawqPrivilege> privileges) {
+ this.privileges = privileges;
+ }
+
+ public boolean isAllowed() {
+ return allowed;
+ }
+
+ public void setAllowed(boolean allowed) {
+ this.allowed = allowed;
+ }
+
+ public Map<HawqResource, String> getResource() {
+ return resource;
+ }
+
+ public void setResource(Map<HawqResource, String> resource) {
+ this.resource = resource;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("resource", resource)
+ .append("privileges", privileges)
+ .append("allowed", allowed)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ResourceAccess that = (ResourceAccess) o;
+ return allowed == that.allowed &&
+ Objects.equals(resource, that.resource) &&
+ Objects.equals(privileges, that.privileges);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(resource, privileges, allowed);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/resources/log4j.properties b/ranger-plugin/service/src/main/resources/log4j.properties
new file mode 100644
index 0000000..6bbdaed
--- /dev/null
+++ b/ranger-plugin/service/src/main/resources/log4j.properties
@@ -0,0 +1,42 @@
+# 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.
+
+# see debug messages during unit tests
+project.root.logger=DEBUG,console
+
+# suppress all logging output during unit tests
+#project.root.logger=FATAL,devnull
+
+#
+# Loggers
+#
+log4j.rootLogger=${project.root.logger}
+
+# ignore most errors from the Apache Ranger and Hadoop for unit tests
+log4j.logger.org.apache.ranger=FATAL
+log4j.logger.org.apache.hadoop=FATAL
+
+#
+# Appenders
+#
+
+# nothing
+log4j.appender.devnull=org.apache.log4j.varia.NullAppender
+
+# console
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml b/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml
new file mode 100644
index 0000000..46dd75d
--- /dev/null
+++ b/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
+ <property>
+ <name>ranger.plugin.hawq.service.name</name>
+ <value>hawq</value>
+ <description>
+ Name of the Ranger service containing policies for this HAWQ instance
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.source.impl</name>
+ <value>org.apache.ranger.admin.client.RangerAdminRESTClient</value>
+ <description>
+ Class to retrieve policies from the source
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.url</name>
+ <value>http://localhost:6080</value>
+ <description>
+ URL to Ranger Admin
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.ssl.config.file</name>
+ <value>/usr/local/hawq/ranger/etc/ranger-policymgr-ssl.xml</value>
+ <description>
+ Path to the file containing SSL details to contact Ranger Admin
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.pollIntervalMs</name>
+ <value>30000</value>
+ <description>
+ How often to poll for changes in policies?
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.cache.dir</name>
+ <value>/usr/local/hawq/ranger/policycache</value>
+ <description>
+ Directory where Ranger policies are cached after successful retrieval from the source
+ </description>
+ </property>
+
+ <!--
+ <property>
+ <name>xasecure.hive.update.xapolicies.on.grant.revoke</name>
+ <value>true</value>
+ <description>Should Hive plugin update Ranger policies for updates to permissions done using GRANT/REVOKE?</description>
+ </property>
+ -->
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.client.connection.timeoutMs</name>
+ <value>120000</value>
+ <description>
+ RangerRESTClient Connection Timeout in Milliseconds
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.client.read.timeoutMs</name>
+ <value>30000</value>
+ <description>
+ RangerRESTClient read Timeout in Milliseconds
+ </description>
+ </property>
+</configuration>
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/resources/rps.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/resources/rps.properties b/ranger-plugin/service/src/main/resources/rps.properties
new file mode 100644
index 0000000..9e2b1f4
--- /dev/null
+++ b/ranger-plugin/service/src/main/resources/rps.properties
@@ -0,0 +1,17 @@
+# 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.
+
+ranger.hawq.instance=hawq
+version=${project.version}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml b/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..36c976f
--- /dev/null
+++ b/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,72 @@
+<?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.
+-->
+
+<web-app version="3.0"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+
+ <!--
+ This is the HAWQ Ranger Plugin Service webapp xml descriptor
+
+ servlet-class Jersey entrypoint class
+ init-param com.sun.jersey.config.property.packages
+ Tells Jersey where are the REST components of this webapp
+ jersey.config.server.provider.scanning.recursive
+ Tells Jersey to recusively scan package for REST resources
+ load-on-startup Initialize the webapp on app server startup
+ servlet-mapping Maps the path of the servlet (ranger-plugin/*)
+ listener A class called after the webapp was initialized and before it's about to go down
+ -->
+
+ <servlet>
+ <servlet-name>HAWQ_Ranger_Plugin_Service</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>com.sun.jersey.config.property.packages</param-name>
+ <param-value>org.apache.hawq.ranger.authorization</param-value>
+ </init-param>
+ <init-param>
+ <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>HAWQ_Ranger_Plugin_Service</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+ <!--
+ <listener>
+ <listener-class>org.apache.hawq.pxf.service.rest.ServletLifecycleListener</listener-class>
+ </listener>
+ -->
+ <!-- log4j configuration
+ Log4jConfigListener looks for a file under log4jConfigLocation.
+ When not using absolute path, the path starts from the webapp root directory.
+ If this file cannot be read, log4j will revert to using the default
+ pxf-log4j.properties inside the webapp. -->
+ <context-param>
+ <param-name>log4jConfigLocation</param-name>
+ <param-value>/etc/pxf/conf/pxf-log4j.properties</param-value>
+ </context-param>
+</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java
new file mode 100644
index 0000000..461864e
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(Utils.class)
+public class RangerHawqAuthorizerAppIdTest {
+
+ @Test
+ public void testAppIdIsSet() {
+ PowerMockito.mockStatic(Utils.class);
+ when(Utils.getAppId()).thenReturn("foo");
+ assertEquals("foo", RangerHawqAuthorizer.getInstance().getRangerPlugin().getAppId());
+ }
+}