You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by db...@apache.org on 2017/01/17 06:39:10 UTC

ambari git commit: AMBARI-19570. Hive View 2.0.0: Enable view of ranger authorization for a table. (dipayanb)

Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 d54fab9ae -> 552c418bc


AMBARI-19570. Hive View 2.0.0: Enable view of ranger authorization for a table. (dipayanb)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/552c418b
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/552c418b
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/552c418b

Branch: refs/heads/branch-2.5
Commit: 552c418bc1f8971a2ef9b959fde30d51edf20df0
Parents: d54fab9
Author: Dipayan Bhowmick <di...@gmail.com>
Authored: Tue Jan 17 12:08:54 2017 +0530
Committer: Dipayan Bhowmick <di...@gmail.com>
Committed: Tue Jan 17 12:08:54 2017 +0530

----------------------------------------------------------------------
 .../view/hive20/actor/MetaDataManager.java      |   8 +-
 .../hive20/resources/system/SystemService.java  |  29 ++
 .../system/ranger/RangerException.java          |  56 ++++
 .../resources/system/ranger/RangerService.java  | 317 +++++++++++++++++++
 .../view/hive20/utils/AuthorizationChecker.java |  74 +++++
 .../resources/ui/app/adapters/application.js    |   1 +
 .../src/main/resources/ui/app/adapters/ping.js  |   5 +
 .../ui/app/configs/table-level-tabs.js          |   6 +
 .../hive20/src/main/resources/ui/app/router.js  |   1 +
 .../databases/database/tables/table/auth.js     |  27 ++
 .../src/main/resources/ui/app/styles/app.scss   |  12 +
 .../templates/components/table-properties.hbs   |   2 +-
 .../database/tables/table/auth-error.hbs        |  35 ++
 .../database/tables/table/auth-loading.hbs      |  23 ++
 .../databases/database/tables/table/auth.hbs    |  53 ++++
 .../views/hive20/src/main/resources/view.xml    |  33 ++
 16 files changed, 677 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/actor/MetaDataManager.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/actor/MetaDataManager.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/actor/MetaDataManager.java
index 43733e4..525ec0d 100644
--- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/actor/MetaDataManager.java
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/actor/MetaDataManager.java
@@ -69,15 +69,15 @@ public class MetaDataManager extends HiveActor {
     ActorRef databaseManager = databaseManagers.get(message.getUsername());
     if (databaseManager == null) {
       databaseManager = createDatabaseManager(message.getUsername(), message.getInstanceName());
-      databaseManagers.put(context.getUsername(), databaseManager);
-      databaseManager.tell(new DatabaseManager.Refresh(context.getUsername()), getSelf());
+      databaseManagers.put(message.getUsername(), databaseManager);
+      databaseManager.tell(new DatabaseManager.Refresh(message.getUsername()), getSelf());
     } else {
       if(message.isImmediate()) {
-        databaseManager.tell(new DatabaseManager.Refresh(context.getUsername(), false), getSelf());
+        databaseManager.tell(new DatabaseManager.Refresh(message.getUsername(), false), getSelf());
       }
       cancelTerminationScheduler(message.getUsername());
     }
-    scheduleTermination(context.getUsername());
+    scheduleTermination(message.getUsername());
   }
 
   private void handleTerminate(Terminate message) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/SystemService.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/SystemService.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/SystemService.java
index 0afe43c..1399ee4 100644
--- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/SystemService.java
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/SystemService.java
@@ -22,16 +22,29 @@ import akka.actor.ActorRef;
 import org.apache.ambari.view.hive20.BaseService;
 import org.apache.ambari.view.hive20.ConnectionSystem;
 import org.apache.ambari.view.hive20.actor.message.Ping;
+import org.apache.ambari.view.hive20.resources.system.ranger.RangerService;
+import org.json.simple.JSONObject;
 
+import javax.inject.Inject;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
+import java.util.List;
 
 /**
  * System services which are required for the working of the application
  */
 public class SystemService extends BaseService {
 
+  private final RangerService rangerService;
+
+  @Inject
+  public SystemService(RangerService rangerService) {
+    this.rangerService = rangerService;
+  }
+
   /**
    * Clients should sent pings to the server at regular interval so that the system could keep alive stuffs or do
    * cleanup work when the pings stops
@@ -45,4 +58,20 @@ public class SystemService extends BaseService {
     metaDataManager.tell(new Ping(context.getUsername(), context.getInstanceName()), ActorRef.noSender());
     return Response.ok().status(Response.Status.NO_CONTENT).build();
   }
+
+
+  /**
+   * Returns if the current user is a cluster operator or ambari administrator
+   */
+  @GET
+  @Path("/ranger/auth")
+  public Response rangerAuth(@QueryParam("database") String database,
+                             @QueryParam("table") String table) {
+
+    List<RangerService.Policy> policies = rangerService.getPolicies(database, table);
+    JSONObject response = new JSONObject();
+    response.put("policies", policies);
+    return Response.ok(response).build();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerException.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerException.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerException.java
new file mode 100644
index 0000000..f32a997
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerException.java
@@ -0,0 +1,56 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.resources.system.ranger;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.json.simple.JSONObject;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Exceptions send by the Authorization API
+ */
+public class RangerException extends WebApplicationException {
+
+  public RangerException(String message, String errorCode, int status, Exception ex) {
+    super(errorEntity(message, errorCode, status, ex));
+  }
+
+  public RangerException(String message, String errorCode, int status) {
+    this(message, errorCode, status, null);
+  }
+
+  protected static Response errorEntity(String message, String errorCode, int status, Exception ex) {
+    Map<String, Object> response = new HashMap<String, Object>();
+    response.put("message", message);
+    response.put("errorCode", errorCode);
+    if (ex != null) {
+      response.put("trace", ExceptionUtils.getStackTrace(ex));
+    }
+
+    JSONObject finalResponse = new JSONObject();
+    finalResponse.put("errors", response);
+    return Response.status(status).entity(new JSONObject(finalResponse)).type(MediaType.APPLICATION_JSON).build();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerService.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerService.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerService.java
new file mode 100644
index 0000000..95ab27c
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/system/ranger/RangerService.java
@@ -0,0 +1,317 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.resources.system.ranger;
+
+import com.google.common.collect.Lists;
+import org.apache.ambari.view.AmbariHttpException;
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.utils.AuthorizationChecker;
+import org.apache.ambari.view.utils.ambari.AmbariApi;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.hbase.util.Strings;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ */
+public class RangerService {
+
+  private static final String RANGER_CONFIG_URL = "/api/v1/clusters/%s/configurations/service_config_versions?service_name=RANGER&is_current=true";
+
+  protected final Logger LOG = LoggerFactory.getLogger(getClass());
+
+  private final AuthorizationChecker authChecker;
+  private final ViewContext context;
+
+  @Inject
+  public RangerService(AuthorizationChecker authChecker, ViewContext context) {
+    this.authChecker = authChecker;
+    this.context = context;
+  }
+
+  public List<Policy> getPolicies(String database, String table) {
+
+
+    if (context.getCluster() == null) {
+      return getPoliciesFromNonAmbariCluster(database, table);
+    } else {
+      if (!authChecker.isOperator()) {
+        LOG.error("User is not authorized to access the table authorization information");
+        throw new RangerException("User " + context.getUsername() + " does not have privilege to access the table authorization information", "NOT_OPERATOR_OR_ADMIN", 400);
+      }
+      return getPoliciesFromAmbariCluster(database, table);
+    }
+
+  }
+
+  private List<Policy> getPoliciesFromAmbariCluster(String database, String table) {
+    String rangerUrl = null;
+    try {
+      rangerUrl = getRangerUrlFromAmbari();
+    } catch (AmbariHttpException e) {
+      LOG.error("Failed to fetch Ranger URL from ambari. Exception: {}", e);
+      throw new RangerException("Failed to fetch Ranger URL from Ambari", "AMBARI_FETCH_FAILED", 500, e);
+    }
+    if (Strings.isEmpty(rangerUrl)) {
+      LOG.info("Ranger url is not configured for the instance");
+      throw new RangerException("Ranger url is not configured in Ambari.", "CONFIGURATION_ERROR", 500);
+    }
+
+    return getPoliciesFromRanger(rangerUrl, database, table);
+  }
+
+  private List<Policy> getPoliciesFromNonAmbariCluster(String database, String table) {
+    String rangerUrl = getRangerUrlFromConfig();
+    if (Strings.isEmpty(rangerUrl)) {
+      LOG.info("Ranger url is not configured for the instance");
+      throw new RangerException("Ranger url is not configured in Ambari Instance.", "CONFIGURATION_ERROR", 500);
+    }
+
+    return getPoliciesFromRanger(rangerUrl, database, table);
+  }
+
+  private List<Policy> getPoliciesFromRanger(String rangerUrl, String database, String table) {
+    RangerCred cred = getRangerCredFromConfig();
+    if (!cred.isValid()) {
+      LOG.info("Ranger username and password are not configured");
+      throw new RangerException("Bad ranger username/password", "CONFIGURATION_ERROR", 500);
+    }
+
+    String rangerResponse = fetchResponseFromRanger(rangerUrl, cred.username, cred.password, database, table);
+    if (Strings.isEmpty(rangerResponse)) {
+      return Lists.newArrayList();
+    }
+
+    return parseResponse(rangerResponse);
+  }
+
+  private List<Policy> parseResponse(String rangerResponse) {
+    JSONArray jsonArray = (JSONArray) JSONValue.parse(rangerResponse);
+    if (jsonArray.size() == 0) {
+      return new ArrayList<>();
+    }
+
+    List<Policy> policies = new ArrayList<>();
+
+    for (Object policy : jsonArray) {
+      JSONObject policyJson = (JSONObject) policy;
+      if ((Boolean) policyJson.get("isEnabled")) {
+        policies.add(parsePolicy(policyJson));
+      }
+    }
+
+    return policies;
+  }
+
+  private Policy parsePolicy(JSONObject policyJson) {
+    String name = (String) policyJson.get("name");
+    JSONArray policyItems = (JSONArray) policyJson.get("policyItems");
+    Policy policy = new Policy(name);
+
+    if (policyItems.size() > 0) {
+      JSONObject policyItem = (JSONObject) policyItems.get(0);
+      JSONArray usersJson = (JSONArray) policyItem.get("users");
+      JSONArray groupsJson = (JSONArray) policyItem.get("groups");
+
+
+      for (Object user : usersJson) {
+        policy.addUser((String) user);
+      }
+
+      for (Object group : groupsJson) {
+        policy.addGroup((String) group);
+      }
+    }
+
+
+    return policy;
+  }
+
+  private String fetchResponseFromRanger(String rangerUrl, String username, String password, String database, String table) {
+
+    String serviceName = context.getProperties().get("hive.ranger.servicename");
+    if(Strings.isEmpty(serviceName)) {
+      LOG.error("Bad service name configured");
+      throw new RangerException("Ranger service name is not configured in Ambari Instance.", "CONFIGURATION_ERROR", 500);
+    }
+
+    Map<String, String> headers = getRangerHeaders(username, password);
+    StringBuilder urlBuilder = getRangerUrl(rangerUrl, database, table, serviceName);
+
+    try {
+      InputStream stream = context.getURLStreamProvider().readFrom(urlBuilder.toString(), "GET", (String) null, headers);
+      if (stream == null) {
+        LOG.error("Ranger returned an empty stream.");
+        throw new RangerException("Ranger returned an empty stream.", "RANGER_ERROR", 500);
+      }
+      return IOUtils.toString(stream);
+    } catch (IOException e) {
+      LOG.error("Bad response from Ranger. Exception: {}", e);
+      throw new RangerException("Bad response from Ranger", "RANGER_ERROR", 500, e);
+    }
+  }
+
+  private StringBuilder getRangerUrl(String rangerUrl, String database, String table, String serviceName) {
+    StringBuilder queryParams = new StringBuilder();
+    if (!Strings.isEmpty(database)) {
+      queryParams.append("resource:database=");
+      queryParams.append(database);
+      if (!Strings.isEmpty(table)) {
+        queryParams.append("&");
+      }
+    }
+
+    if (!Strings.isEmpty(table)) {
+      queryParams.append("resource:table=");
+      queryParams.append(table);
+    }
+
+
+    String queryParamString = queryParams.toString();
+
+    StringBuilder urlBuilder = new StringBuilder();
+    urlBuilder.append(rangerUrl);
+    urlBuilder.append("/service/public/v2/api/service/");
+    urlBuilder.append(serviceName);
+    urlBuilder.append("/policy");
+    if (!Strings.isEmpty(queryParamString)) {
+      urlBuilder.append("?");
+      urlBuilder.append(queryParamString);
+    }
+    return urlBuilder;
+  }
+
+  private Map<String, String> getRangerHeaders(String username, String password) {
+    String authString = username + ":" + password;
+    byte[] authBytes = Base64.encodeBase64(authString.getBytes());
+    String auth = new String(authBytes);
+    Map<String, String> headers = new HashMap<>();
+    headers.put("Authorization", "Basic " + auth);
+    return headers;
+  }
+
+  private RangerCred getRangerCredFromConfig() {
+    return new RangerCred(context.getProperties().get("hive.ranger.username"),
+        context.getProperties().get("hive.ranger.password"));
+  }
+
+  public String getRangerUrlFromAmbari() throws AmbariHttpException {
+
+    AmbariApi ambariApi = new AmbariApi(context);
+    String url = String.format(RANGER_CONFIG_URL, context.getCluster().getName());
+    String config = ambariApi.readFromAmbari(url, "GET", null, null);
+    JSONObject configJson = (JSONObject) JSONValue.parse(config);
+    JSONArray itemsArray = (JSONArray) configJson.get("items");
+    if (itemsArray.size() == 0) {
+      LOG.error("Ranger service is not enabled in Ambari");
+      throw new RangerException("Ranger service is not enabled in Ambari", "SERVICE_ERROR", 500);
+    }
+    JSONObject item = (JSONObject) itemsArray.get(0);
+    JSONArray configurations = (JSONArray) item.get("configurations");
+    for (Object configuration : configurations) {
+      JSONObject configurationJson = (JSONObject) configuration;
+      String type = (String) configurationJson.get("type");
+      if (type.equalsIgnoreCase("admin-properties")) {
+        JSONObject properties = (JSONObject) configurationJson.get("properties");
+        return (String) properties.get("policymgr_external_url");
+      }
+    }
+    return null;
+  }
+
+  public String getRangerUrlFromConfig() {
+    return context.getProperties().get("hive.ranger.url");
+  }
+
+  /**
+   * POJO class to store the policy information from Ranger
+   */
+  public static class Policy {
+    private String name;
+    private List<String> users = new ArrayList<>();
+    private List<String> groups = new ArrayList<>();
+
+    public Policy(String name) {
+      this.name = name;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
+    public List<String> getUsers() {
+      return users;
+    }
+
+    public void setUsers(List<String> users) {
+      this.users = users;
+    }
+
+    public List<String> getGroups() {
+      return groups;
+    }
+
+    public void setGroups(List<String> groups) {
+      this.groups = groups;
+    }
+
+
+    public void addUser(String user) {
+      users.add(user);
+    }
+
+    public void addGroup(String group) {
+      groups.add(group);
+    }
+  }
+
+  /**
+   * POJO class to store the username and password for ranger access
+   */
+  private class RangerCred {
+    public String username;
+    public String password;
+
+    public RangerCred(String username, String password) {
+      this.username = username;
+      this.password = password;
+    }
+
+    public boolean isValid() {
+      return !(Strings.isEmpty(username) || Strings.isEmpty(password));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/utils/AuthorizationChecker.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/utils/AuthorizationChecker.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/utils/AuthorizationChecker.java
new file mode 100644
index 0000000..3121ba0
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/utils/AuthorizationChecker.java
@@ -0,0 +1,74 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.utils;
+
+import org.apache.ambari.view.AmbariHttpException;
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.utils.ambari.AmbariApi;
+import org.apache.ambari.view.utils.ambari.NoClusterAssociatedException;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+
+/**
+ * Utility class to check the authorization of the user
+ */
+public class AuthorizationChecker {
+  protected final Logger LOG = LoggerFactory.getLogger(getClass());
+  private static final String AMBARI_OR_CLUSTER_ADMIN_PRIVILEGE_URL = "/api/v1/users/%s?privileges/PrivilegeInfo/permission_name=AMBARI.ADMINISTRATOR|" +
+      "(privileges/PrivilegeInfo/permission_name.in(CLUSTER.ADMINISTRATOR,CLUSTER.OPERATOR)&privileges/PrivilegeInfo/cluster_name=%s)";
+
+  private final ViewContext viewContext;
+  private final AmbariApi ambariApi;
+
+
+  @Inject
+  public AuthorizationChecker(ViewContext viewContext) {
+    this.viewContext = viewContext;
+    this.ambariApi = new AmbariApi(viewContext);
+  }
+
+  public boolean isOperator() {
+    if (viewContext.getCluster() == null) {
+      throw new NoClusterAssociatedException("No cluster is associated with the current instance");
+    }
+    String fetchUrl = String.format(AMBARI_OR_CLUSTER_ADMIN_PRIVILEGE_URL, viewContext.getUsername(), viewContext.getCluster().getName());
+
+    try {
+      String response = ambariApi.readFromAmbari(fetchUrl, "GET", null, null);
+
+      if (response != null && !response.isEmpty()) {
+        JSONObject json = (JSONObject) JSONValue.parse(response);
+        if (json.containsKey("privileges")) {
+          JSONArray privileges = (JSONArray) json.get("privileges");
+          if (privileges.size() > 0) return true;
+        }
+      }
+
+    } catch (AmbariHttpException e) {
+      LOG.error("Got Error response from url : {}. Response : {}", fetchUrl, e.getMessage(), e);
+    }
+
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/adapters/application.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/adapters/application.js b/contrib/views/hive20/src/main/resources/ui/app/adapters/application.js
index 82d53e4..c0189cc 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/adapters/application.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/adapters/application.js
@@ -56,6 +56,7 @@ export default DS.RESTAdapter.extend({
       // by setting the proxyurl parameter in ember serve and for ambari to authenticate the requests, it needs this
       // basic authorization. This is for default admin/admin username/password combination.
       headers['Authorization'] = 'Basic YWRtaW46YWRtaW4=';
+      //headers['Authorization'] = 'Basic aGl2ZTpoaXZl';
     }
      return headers;
   }),

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/adapters/ping.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/adapters/ping.js b/contrib/views/hive20/src/main/resources/ui/app/adapters/ping.js
index 20c6d9c..f88cfed 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/adapters/ping.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/adapters/ping.js
@@ -26,5 +26,10 @@ export default ApplicationAdapter.extend({
 
   pathForType() {
     return "system/ping";
+  },
+
+  fetchAuth(databaseName, tableName) {
+    const url = this.buildURL() + '/system/ranger/auth';
+    return this.ajax(url, "GET", {data: {database: databaseName, table: tableName}});
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/configs/table-level-tabs.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/configs/table-level-tabs.js b/contrib/views/hive20/src/main/resources/ui/app/configs/table-level-tabs.js
index 7a0cec1..ab7125a 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/configs/table-level-tabs.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/configs/table-level-tabs.js
@@ -60,6 +60,12 @@ let tableLevelTabs = [
     label: 'STATISTICS',
     link: 'databases.database.tables.table.stats',
     faIcon: 'line-chart'
+  }),
+  Ember.Object.create({
+    name: 'authorization',
+    label: 'AUTHORIZATION',
+    link: 'databases.database.tables.table.auth',
+    faIcon: 'users'
   })
 ];
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/router.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/router.js b/contrib/views/hive20/src/main/resources/ui/app/router.js
index 692cefd..e32dfe8 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/router.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/router.js
@@ -42,6 +42,7 @@ Router.map(function() {
           this.route('view');
           this.route('ddl');
           this.route('stats');
+          this.route('auth');
         })
       });
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/table/auth.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/table/auth.js b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/table/auth.js
new file mode 100644
index 0000000..ec9d1a2
--- /dev/null
+++ b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/table/auth.js
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+
+import TableMetaRouter from './table-meta-router';
+
+export default TableMetaRouter.extend({
+  model(params, transition) {
+    let databaseName = transition.params['databases.database']['databaseId'];
+    let tableName = transition.params['databases.database.tables.table']['name'];
+    return this.store.adapterFor('ping').fetchAuth(databaseName, tableName);
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss b/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss
index 8e0ab21..5ae65d1 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss
+++ b/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss
@@ -805,6 +805,18 @@ pre {
 }
 
 
+.loader {
+  padding-top: 25px;
+  padding-bottom: 25px;
+}
+
+.authorizations {
+  &.alert {
+    margin: 0;
+  }
+}
+
+
 
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/templates/components/table-properties.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/components/table-properties.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/components/table-properties.hbs
index 0eaab5e..953ef84 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/templates/components/table-properties.hbs
+++ b/contrib/views/hive20/src/main/resources/ui/app/templates/components/table-properties.hbs
@@ -33,7 +33,7 @@
   {{/each}}
   <tr class="new-settings text-center">
     <td colspan="3">
-      <a {{action "addNewRow"}}>{{fa-icon "plus"}} Add New Column</a>
+      <a {{action "addNewRow"}}>{{fa-icon "plus"}} Add New Properties</a>
     </td>
   </tr>
   </tbody>

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-error.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-error.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-error.hbs
new file mode 100644
index 0000000..db3d3f2
--- /dev/null
+++ b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-error.hbs
@@ -0,0 +1,35 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class="row">
+  <div class="authorizations alert alert-info">
+    <p class="lead">{{fa-icon "shield" size=1}} Ranger policies</p>
+  </div>
+</div>
+<div class="row">
+  <div class="col-md-12 alert alert-danger">
+    <p><strong>Message:</strong> {{model.errors.message}}</p>
+    <p><strong>Error Code:</strong> {{model.errors.errorCode}}</p>
+    {{#if model.errors.trace}}
+      <p><strong>Trace:</strong></p>
+      <pre class="prettyprint">
+        {{model.errors.trace}}
+      </pre>
+    {{/if}}
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-loading.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-loading.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-loading.hbs
new file mode 100644
index 0000000..fbeb1a8
--- /dev/null
+++ b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth-loading.hbs
@@ -0,0 +1,23 @@
+{{!
+* 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.
+}}
+
+<div class="col-md-12 text-center loader">
+  {{fa-icon "spinner" spin=true size=3}}
+  <br>
+  <h3>Loading authorization information from Ranger</h3>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth.hbs
new file mode 100644
index 0000000..f717bcc
--- /dev/null
+++ b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/table/auth.hbs
@@ -0,0 +1,53 @@
+{{!
+* 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.
+}}
+<div class="row">
+  <div class="authorizations alert alert-info">
+    <p class="lead">{{fa-icon "shield" size=1}} Ranger policies</p>
+  </div>
+</div>
+
+<div class="row">
+  <table class="table table-bordered table-hover">
+    <thead>
+    <tr>
+      <th width="20%">POLICY NAME</th>
+      <th width="40%">USERS</th>
+      <th width="40%">GROUPS</th>
+    </tr>
+    </thead>
+    <tbody>
+    {{#each model.policies as |policy|}}
+      <tr>
+        <td>{{policy.name}}</td>
+        <td>
+          {{#each policy.users as |user|}}
+            <span class="label label-success">{{user}}</span>
+          {{/each}}
+        </td>
+        <td>
+          {{#each policy.groups as |group|}}
+            <span class="label label-success">{{group}}</span>
+          {{/each}}
+        </td>
+      </tr>
+    {{/each}}
+    </tbody>
+  </table>
+</div>
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/552c418b/contrib/views/hive20/src/main/resources/view.xml
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/view.xml b/contrib/views/hive20/src/main/resources/view.xml
index 2cbfef0..7cbe15c 100644
--- a/contrib/views/hive20/src/main/resources/view.xml
+++ b/contrib/views/hive20/src/main/resources/view.xml
@@ -57,6 +57,30 @@
     </parameter>
 
     <parameter>
+        <name>hive.ranger.servicename</name>
+        <description>Set the service name of ranger configured for this hive cluster</description>
+        <label>Ranger Service Name</label>
+        <placeholder>c1_hive</placeholder>
+        <required>false</required>
+    </parameter>
+
+    <parameter>
+        <name>hive.ranger.username</name>
+        <description>Admin username for ranger</description>
+        <label>Ranger Username</label>
+        <default-value>admin</default-value>
+        <required>false</required>
+    </parameter>
+    <parameter>
+        <name>hive.ranger.password</name>
+        <description>Admin password for ranger</description>
+        <label>Ranger Password</label>
+        <default-value>admin</default-value>
+        <masked>true</masked>
+        <required>false</required>
+    </parameter>
+
+    <parameter>
         <name>hive.metastore.warehouse.dir</name>
         <description>Hive Metastore directory (example: /apps/hive/warehouse)</description>
         <label>Hive Metastore directory</label>
@@ -149,6 +173,15 @@
     </parameter>
 
     <parameter>
+        <name>hive.ranger.url</name>
+        <description>Ranger URL</description>
+        <label>Ranger URL</label>
+        <placeholder>http://rangerhost:post</placeholder>
+        <cluster-config>fake</cluster-config>
+        <required>false</required>
+    </parameter>
+
+    <parameter>
         <name>webhdfs.username</name>
         <description>doAs for proxy user for HDFS. By default, uses the currently logged-in Ambari user.</description>
         <label>WebHDFS Username</label>