You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by ak...@apache.org on 2017/01/24 23:03:23 UTC

[01/12] sentry git commit: General cleanup

Repository: sentry
Updated Branches:
  refs/heads/akolb-ha-cli [created] e75e825fc


General cleanup


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

Branch: refs/heads/akolb-ha-cli
Commit: e75e825fc83c36678a7861909b0ec4c294532e16
Parents: 6ae74f3
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Thu Dec 15 18:03:50 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../org/apache/sentry/shell/GroupShell.java     |  4 +--
 .../org/apache/sentry/shell/PrivsShell.java     |  4 +--
 .../org/apache/sentry/shell/RolesShell.java     |  2 +-
 .../java/org/apache/sentry/shell/SentryCli.java | 26 +++-----------------
 .../java/org/apache/sentry/shell/ShellUtil.java |  8 ++----
 .../org/apache/sentry/shell/TopLevelShell.java  |  2 +-
 6 files changed, 11 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/e75e825f/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
index 246509c..a69557b 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
@@ -56,10 +56,10 @@ public class GroupShell implements ShellDependent {
     }
 
     private final ShellUtil tools;
-    Shell shell;
+    private Shell shell;
 
 
-    public GroupShell(SentryPolicyServiceClient sentryClient, String authUser) {
+    GroupShell(SentryPolicyServiceClient sentryClient, String authUser) {
         this.tools = new ShellUtil(sentryClient, authUser);
     }
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/e75e825f/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
index 2e12be8..9b6bf9b 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
@@ -28,7 +28,7 @@ import java.util.List;
 
 public class PrivsShell implements ShellDependent {
     private final ShellUtil tools;
-    Shell shell;
+    private Shell shell;
 
     @Command(description = "Grant privilege to role")
     public void grant(
@@ -60,7 +60,7 @@ public class PrivsShell implements ShellDependent {
         tools.revokePrivilegeFromRole(roleName, privilege);
     }
 
-    public PrivsShell(SentryPolicyServiceClient sentryClient, String authUser) {
+    PrivsShell(SentryPolicyServiceClient sentryClient, String authUser) {
         this.tools = new ShellUtil(sentryClient, authUser);
     }
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/e75e825f/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
index 9ac6637..dc72382 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
@@ -65,7 +65,7 @@ public class RolesShell implements ShellDependent {
     private final ShellUtil tools;
     Shell shell;
 
-    public RolesShell(SentryPolicyServiceClient sentryClient, String authUser) {
+    RolesShell(SentryPolicyServiceClient sentryClient, String authUser) {
         this.tools = new ShellUtil(sentryClient, authUser);
     }
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/e75e825f/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
index 36833c8..ea5415d 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
@@ -25,8 +25,6 @@ import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.log4j.PropertyConfigurator;
 import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
 import org.apache.sentry.service.thrift.SentryServiceClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -42,7 +40,6 @@ import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SEC
  * Sentry interactive tool
  */
 public class SentryCli {
-    private static final Logger log = LoggerFactory.getLogger(SentryCli.class.getName());
     private static final String LOG4J_CONF = "log4jConf";
     private final String[] args;
     private Options options = new Options();
@@ -63,11 +60,11 @@ public class SentryCli {
 
     private SentryPolicyServiceClient sentryClient;
 
-    public SentryPolicyServiceClient getSentryClient() {
+    private SentryPolicyServiceClient getSentryClient() {
         return sentryClient;
     }
 
-    public String getRequestorName() {
+    private String getRequestorName() {
         return requestorName;
     }
 
@@ -85,7 +82,7 @@ public class SentryCli {
      * Construct SentryCli from arguments
      * @param args command-line arguments
      */
-    public SentryCli(String[] args) {
+    private SentryCli(String[] args) {
         this.args = args;
         options.addOption("h", "help", false, "show help");
         // file path of sentry-site
@@ -106,23 +103,6 @@ public class SentryCli {
     }
 
     /**
-     * Parse command-line arguments.
-     */
-    public void parse() {
-        CommandLineParser parser = new GnuParser();
-        try {
-            cmd = parser.parse(options, args);
-            if (cmd.hasOption("h")) {
-                help();
-            }
-        } catch (ParseException e) {
-            log.warn("error in parsing expression", e);
-            help();
-            System.exit(1);
-        }
-    }
-
-    /**
      * Initialize CLI
      */
     private void init() {

http://git-wip-us.apache.org/repos/asf/sentry/blob/e75e825f/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
index 007975c..2b08684 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
@@ -35,7 +35,6 @@ import static org.apache.sentry.service.thrift.SentryServiceUtil.convertToTSentr
 class ShellUtil {
 
     List<String> listRoles() {
-        List<String> roles = null;
         try {
             return getRoles();
         } catch (SentryUserException e) {
@@ -213,7 +212,6 @@ class ShellUtil {
             if (ServiceConstants.PrivilegeScope.URI.toString().equals(tPriv.getPrivilegeScope())) {
                 sentryClient.grantURIPrivilege(authUser, roleName, tPriv.getServerName(),
                         tPriv.getURI(), grantOption);
-                return;
             }
         } catch (SentryUserException e) {
             System.out.println("Error granting privilege: " + e.toString());
@@ -275,7 +273,7 @@ class ShellUtil {
 
     void revokePrivilegeFromRole(String roleName, String privilegeStr) {
         TSentryPrivilege tSentryPrivilege = convertToTSentryPrivilege(privilegeStr);
-        boolean grantOption = tSentryPrivilege.getGrantOption().equals(TSentryGrantOption.TRUE) ? true : false;
+        boolean grantOption = tSentryPrivilege.getGrantOption().equals(TSentryGrantOption.TRUE);
 
         try {
             if (ServiceConstants.PrivilegeScope.SERVER.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
@@ -303,7 +301,6 @@ class ShellUtil {
             if (ServiceConstants.PrivilegeScope.URI.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
                 sentryClient.revokeURIPrivilege(authUser, roleName, tSentryPrivilege.getServerName(),
                         tSentryPrivilege.getURI(), grantOption);
-                return;
             }
         } catch (SentryUserException e) {
             System.out.println("failed to revoke privilege: " + e.toString());
@@ -313,8 +310,7 @@ class ShellUtil {
 
     private List<String>getRoles() throws SentryUserException {
         // Collect role names
-        Set<TSentryRole> roles = null;
-        roles = sentryClient.listRoles(authUser);
+        final Set<TSentryRole> roles = sentryClient.listRoles(authUser);
         List<String> roleNames = new ArrayList<>();
         for(TSentryRole role: roles) {
             roleNames.add(role.getRoleName());

http://git-wip-us.apache.org/repos/asf/sentry/blob/e75e825f/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index 047f11c..e004776 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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


[08/12] sentry git commit: Added sentry-tools to poms

Posted by ak...@apache.org.
Added sentry-tools to poms


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/0580230c
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/0580230c
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/0580230c

Branch: refs/heads/akolb-ha-cli
Commit: 0580230cba9665a4bc50841aee8fcbe352ab266a
Parents: f8cc8ea
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Tue Dec 13 16:39:18 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 sentry-dist/pom.xml  |  5 +++++
 sentry-tools/pom.xml | 16 ++++++++++++++++
 2 files changed, 21 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/0580230c/sentry-dist/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-dist/pom.xml b/sentry-dist/pom.xml
index 14f6ba1..d605eb1 100644
--- a/sentry-dist/pom.xml
+++ b/sentry-dist/pom.xml
@@ -99,6 +99,11 @@ limitations under the License.
       <artifactId>sentry-hdfs-dist</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.sentry</groupId>
+      <artifactId>sentry-tools</artifactId>
+      <version>1.8.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.39</version>

http://git-wip-us.apache.org/repos/asf/sentry/blob/0580230c/sentry-tools/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-tools/pom.xml b/sentry-tools/pom.xml
index 62dd862..a46319b 100644
--- a/sentry-tools/pom.xml
+++ b/sentry-tools/pom.xml
@@ -1,4 +1,20 @@
 <?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">


[10/12] sentry git commit: Support listing/removal of all privileges

Posted by ak...@apache.org.
Support listing/removal of all privileges


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

Branch: refs/heads/akolb-ha-cli
Commit: f2ab8cb3b3378fa33c9e21ea04069f219e6ee512
Parents: 0580230
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Tue Dec 13 18:29:26 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../org/apache/sentry/shell/PrivsShell.java     |  9 ++
 .../java/org/apache/sentry/shell/ShellUtil.java | 97 +++++++++++++++++---
 .../org/apache/sentry/shell/TopLevelShell.java  | 20 ++++
 3 files changed, 112 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/f2ab8cb3/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
index cf2ebbd..82369cd 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
@@ -35,10 +35,19 @@ public class PrivsShell implements ShellDependent {
     }
 
     @Command
+    public String list() {
+        return tools.listPrivileges();
+    }
+
+    @Command
     public List<String> list(String roleName) {
         return tools.listPrivileges(roleName);
     }
 
+    @Command
+    public void revoke(String roleName, String privilege) {
+        tools.revokePrivilegeFromRole(roleName, privilege);
+    }
 
     public PrivsShell(SentryPolicyServiceClient sentryClient, String authUser) {
         this.tools = new ShellUtil(sentryClient, authUser);

http://git-wip-us.apache.org/repos/asf/sentry/blob/f2ab8cb3/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
index fbd382a..4decf28 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
@@ -22,7 +22,6 @@ import com.google.common.collect.Sets;
 import org.apache.commons.lang.StringUtils;
 import org.apache.sentry.core.common.exception.SentryUserException;
 import org.apache.sentry.provider.db.service.thrift.*;
-import org.apache.sentry.service.thrift.SentryServiceUtil;
 import org.apache.sentry.service.thrift.ServiceConstants;
 
 import java.util.*;
@@ -36,23 +35,13 @@ import static org.apache.sentry.service.thrift.SentryServiceUtil.convertToTSentr
 class ShellUtil {
 
     List<String> listRoles() {
-        Set<TSentryRole> roles = null;
+        List<String> roles = null;
         try {
-            roles = sentryClient.listRoles(authUser);
+            return getRoles();
         } catch (SentryUserException e) {
             System.out.println("Error listing roles: " + e.toString());
         }
-        List<String> result = new ArrayList<>();
-        if (roles == null || roles.isEmpty()) {
-            return result;
-        }
-
-        for(TSentryRole role: roles) {
-            result.add(role.getRoleName());
-        }
-
-        Collections.sort(result);
-        return result;
+        return new LinkedList<>();
     }
 
     List<String> listRoles(String group) {
@@ -252,6 +241,86 @@ class ShellUtil {
         return result;
     }
 
+    /**
+     * List all privileges
+     * @return string with privilege info for all roles
+     */
+    String listPrivileges() {
+        List<String> roles = null;
+        try {
+            roles = getRoles();
+        } catch (SentryUserException e) {
+            System.out.println("failed to get role names: " + e.toString());
+        }
+
+        if (roles == null || roles.isEmpty()) {
+            return "";
+        }
+
+        StringBuilder result = new StringBuilder();
+        for (String role: roles) {
+            List<String> privs = listPrivileges(role);
+            if (privs.isEmpty()) {
+                continue;
+            }
+            result.append(role).append(" = ");
+            result.append(StringUtils.join(listPrivileges(role), ",\n\t"));
+            result.append('\n');
+        }
+        return result.toString();
+    }
+
+    void revokePrivilegeFromRole(String roleName, String privilegeStr) {
+        TSentryPrivilege tSentryPrivilege = convertToTSentryPrivilege(privilegeStr);
+        boolean grantOption = tSentryPrivilege.getGrantOption().equals(TSentryGrantOption.TRUE) ? true : false;
+
+        try {
+            if (ServiceConstants.PrivilegeScope.SERVER.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+                sentryClient.revokeServerPrivilege(authUser, roleName, tSentryPrivilege.getServerName(),
+                        grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.DATABASE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+                sentryClient.revokeDatabasePrivilege(authUser, roleName, tSentryPrivilege.getServerName(),
+                        tSentryPrivilege.getDbName(), tSentryPrivilege.getAction(), grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.TABLE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+                sentryClient.revokeTablePrivilege(authUser, roleName, tSentryPrivilege.getServerName(),
+                        tSentryPrivilege.getDbName(), tSentryPrivilege.getTableName(),
+                        tSentryPrivilege.getAction(), grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.COLUMN.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+                sentryClient.revokeColumnPrivilege(authUser, roleName, tSentryPrivilege.getServerName(),
+                        tSentryPrivilege.getDbName(), tSentryPrivilege.getTableName(),
+                        tSentryPrivilege.getColumnName(), tSentryPrivilege.getAction(), grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.URI.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+                sentryClient.revokeURIPrivilege(authUser, roleName, tSentryPrivilege.getServerName(),
+                        tSentryPrivilege.getURI(), grantOption);
+                return;
+            }
+        } catch (SentryUserException e) {
+            System.out.println("failed to revoke privilege: " + e.toString());
+        }
+    }
+
+
+    private List<String>getRoles() throws SentryUserException {
+        // Collect role names
+        Set<TSentryRole> roles = null;
+        roles = sentryClient.listRoles(authUser);
+        List<String> roleNames = new ArrayList<>();
+        for(TSentryRole role: roles) {
+            roleNames.add(role.getRoleName());
+        }
+
+        Collections.sort(roleNames);
+        return roleNames;
+    }
+
     ShellUtil(SentryPolicyServiceClient sentryClient, String authUser) {
         this.sentryClient = sentryClient;
         this.authUser = authUser;

http://git-wip-us.apache.org/repos/asf/sentry/blob/f2ab8cb3/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index b677f0f..d5d74b4 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -108,6 +108,26 @@ public class TopLevelShell implements ShellDependent, Runnable {
         tools.removeRoles(roles);
     }
 
+    @Command(description = "list Sentry privileges")
+    public String listPrivileges() {
+        return tools.listPrivileges();
+    }
+
+    @Command(description = "list Sentry privileges")
+    public List<String> listPrivileges(String roleName) {
+        return tools.listPrivileges(roleName);
+    }
+
+    @Command(description = "Grant privilege to role")
+    public void grantPrivilege(String roleName, String privilege) {
+        tools.grantPrivilegeToRole(roleName, privilege);
+    }
+
+    @Command
+    public void revokePrivilege(String roleName, String privilege) {
+        tools.revokePrivilegeFromRole(roleName, privilege);
+    }
+
     @Override
     public void cliSetShell(Shell theShell) {
         this.shell = theShell;


[06/12] sentry git commit: HA version of interactive CLI

Posted by ak...@apache.org.
HA version of interactive CLI


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

Branch: refs/heads/akolb-ha-cli
Commit: bc23df3ff6faafe0ff7f1a379a8267f7e9693ab1
Parents: d7a183b
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Mon Dec 12 14:15:26 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../main/java/org/apache/sentry/SentryMain.java |   2 +
 .../provider/db/tools/cli/GroupShell.java       |  65 ++++++
 .../provider/db/tools/cli/RolesShell.java       |  72 +++++++
 .../sentry/provider/db/tools/cli/SentryCli.java | 172 ++++++++++++++++
 .../sentry/provider/db/tools/cli/ShellUtil.java | 205 +++++++++++++++++++
 .../provider/db/tools/cli/TopLevelShell.java    |  93 +++++++++
 .../sentry/provider/db/cli/GroupShell.java      |  65 ------
 .../sentry/provider/db/cli/RolesShell.java      |  72 -------
 .../sentry/provider/db/cli/SentryCli.java       | 172 ----------------
 .../sentry/provider/db/cli/ShellUtil.java       | 205 -------------------
 .../sentry/provider/db/cli/TopLevelShell.java   |  93 ---------
 11 files changed, 609 insertions(+), 607 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/SentryMain.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/SentryMain.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/SentryMain.java
index d321531..05a0714 100644
--- a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/SentryMain.java
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/SentryMain.java
@@ -77,10 +77,12 @@ public class SentryMain {
       if (!log4jProperties.containsKey("log4j.category.DataNucleus.Query")) {
         log4jProperties.setProperty("log4j.category.DataNucleus.Query", "INFO");
 
+        /*
         // Enable debug log for DataNucleus.Query only when log.threshold is TRACE
         if (log4jProperties.getProperty("log.threshold").equalsIgnoreCase("TRACE")) {
           log4jProperties.setProperty("log4j.category.DataNucleus.Query", "DEBUG");
         }
+        */
       }
 
       PropertyConfigurator.configure(log4jProperties);

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java
new file mode 100644
index 0000000..d4b0bd7
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.sentry.provider.db.tools.cli;
+
+import com.budhash.cliche.Command;
+import com.budhash.cliche.Shell;
+import com.budhash.cliche.ShellDependent;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.util.List;
+
+/**
+ * Sentry group manipulation for CLI
+ */
+public class GroupShell implements ShellDependent {
+    @Command
+    public List<String> list() {
+        return tools.listGroups();
+    }
+
+    @Command(abbrev = "lr", header = "[groups]",
+            description = "list groups and their roles")
+    public List<String> listRoles() {
+        return tools.listGroupRoles();
+    }
+
+    @Command(description = "Grant role to groups")
+    public void grant(String roleName, String ...groups) {
+        tools.grantGroupsToRole(roleName, groups);
+    }
+
+    @Command(description = "Revoke role from groups")
+    public void revoke(String roleName, String ...groups) {
+        tools.revokeGroupsFromRole(roleName, groups);
+    }
+
+    private final ShellUtil tools;
+    Shell shell;
+
+
+    public GroupShell(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.tools = new ShellUtil(sentryClient, authUser);
+    }
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java
new file mode 100644
index 0000000..71f0cab
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java
@@ -0,0 +1,72 @@
+/*
+ * 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.sentry.provider.db.tools.cli;
+
+import com.budhash.cliche.Command;
+import com.budhash.cliche.Param;
+import com.budhash.cliche.Shell;
+import com.budhash.cliche.ShellDependent;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.util.List;
+
+/**
+ * Sentry roles manipulation for CLI.
+ */
+public class RolesShell implements ShellDependent {
+    @Command(description = "List sentry roles. shows all available roles.")
+    public List<String> list() {
+        return tools.listRoles();
+    }
+
+    @Command(description = "List sentry roles by group")
+    public List<String> list(
+            @Param(name = "groupName", description = "group name for roles")
+            String group) {
+        return tools.listRoles(group);
+    }
+
+    @Command(description = "Create Sentry role(s).")
+    public void create(
+            @Param(name = "roleName", description = "name of role to create")
+            String ...roles) {
+        tools.createRoles(roles);
+    }
+
+    @Command(description = "remove Sentry role(s).")
+    public void remove(
+            @Param(name = "roleName ...", description = "role names to remove")
+            String ...roles) {
+        tools.removeRoles(roles);
+    }
+
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+
+    private final ShellUtil tools;
+    Shell shell;
+
+    public RolesShell(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.tools = new ShellUtil(sentryClient, authUser);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java
new file mode 100644
index 0000000..f9bbfd3
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java
@@ -0,0 +1,172 @@
+/**
+ * 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.sentry.provider.db.tools.cli;
+
+import org.apache.commons.cli.*;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.service.thrift.SentryServiceClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Sentry interactive tool
+ */
+public class SentryCli {
+    private static final Logger log = LoggerFactory.getLogger(SentryCli.class.getName());
+    private static final String LOG4J_CONF = "log4jConf";
+    private final String[] args;
+    private Options options = new Options();
+    private CommandLine cmd;
+
+    private static final String configOpt = "config";
+    private static final String userOpt = "user";
+
+    private SentryPolicyServiceClient sentryClient;
+
+    public SentryPolicyServiceClient getSentryClient() {
+        return sentryClient;
+    }
+
+    public String getRequestorName() {
+        return requestorName;
+    }
+
+    private String requestorName;
+
+    public static void main(String[] args) {
+        SentryCli cli = new SentryCli(args);
+        // Create interactive shell and run it
+        TopLevelShell shell = new TopLevelShell(cli.getSentryClient(),
+                cli.getRequestorName());
+        shell.run();
+    }
+
+    /**
+     * Construct SentryCli from arguments
+     * @param args command-line arguments
+     */
+    public SentryCli(String[] args) {
+        this.args = args;
+        options.addOption("h", "help", false, "show help");
+        // file path of sentry-site
+        options.addOption("U", userOpt, true, "auth user");
+        options.addOption("c", configOpt, true, "sentry configuration");
+        options.addOption("L", LOG4J_CONF, true, "Location of log4j properties file");
+        CommandLineParser parser = new GnuParser();
+        try {
+            this.cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            help();
+        }
+        if (cmd.hasOption("h")) {
+            help();
+        }
+        init();
+    }
+
+    /**
+     * Parse command-line arguments.
+     */
+    public void parse() {
+        CommandLineParser parser = new GnuParser();
+        try {
+            cmd = parser.parse(options, args);
+            if (cmd.hasOption("h")) {
+                help();
+            }
+        } catch (ParseException e) {
+            log.warn("error in parsing expression", e);
+            help();
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Initialize CLI
+     */
+    private void init() {
+        Map<String, String> env = System.getenv();
+        String pathConf = cmd.getOptionValue(configOpt);
+        if (pathConf == null) {
+            pathConf = env.get("SENTRY_CONFIG");
+        }
+        if (pathConf == null) {
+            System.out.println("Missing config file");
+            System.exit(1);
+        }
+
+        String log4jconf = cmd.getOptionValue(LOG4J_CONF);
+        if (log4jconf != null && log4jconf.length() > 0) {
+            Properties log4jProperties = new Properties();
+
+            // Firstly load log properties from properties file
+            FileInputStream istream = null;
+            try {
+                istream = new FileInputStream(log4jconf);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+            try {
+                log4jProperties.load(istream);
+                istream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            PropertyConfigurator.configure(log4jProperties);
+        }
+        Configuration conf = new Configuration();
+        conf.addResource(new Path(pathConf));
+
+        requestorName = cmd.getOptionValue(userOpt, "");
+        if (requestorName.isEmpty()) {
+            UserGroupInformation ugi = null;
+            try {
+                ugi = UserGroupInformation.getLoginUser();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            requestorName = ugi.getShortUserName();
+        }
+
+        try {
+            sentryClient = SentryServiceClientFactory.create(conf);
+        } catch (Exception e) {
+            System.out.println("Failed to connect to Sentry server: " + e.toString());
+        }
+    }
+
+    private void help() {
+        // This prints out some help
+        HelpFormatter formater = new HelpFormatter();
+        formater.printHelp("sentrycli", options);
+        System.exit(0);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java
new file mode 100644
index 0000000..3d61405
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java
@@ -0,0 +1,205 @@
+/*
+ * 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.sentry.provider.db.tools.cli;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+
+import java.util.*;
+
+/**
+ * ShellUtil implements actual commands
+ */
+class ShellUtil {
+
+    List<String> listRoles() {
+        Set<TSentryRole> roles = null;
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error listing roles: " + e.toString());
+        }
+        List<String> result = new ArrayList<>();
+        if (roles == null || roles.isEmpty()) {
+            return result;
+        }
+
+        for(TSentryRole role: roles) {
+            result.add(role.getRoleName());
+        }
+
+        Collections.sort(result);
+        return result;
+    }
+
+    List<String> listRoles(String group) {
+        Set<TSentryRole> roles = null;
+        try {
+            roles = sentryClient.listRolesByGroupName(authUser, group);
+        } catch (SentryUserException e) {
+            System.out.println("Error listing roles: " + e.toString());
+        }
+        List<String> result = new ArrayList<>();
+        if (roles == null || roles.isEmpty()) {
+            return result;
+        }
+
+        for(TSentryRole role: roles) {
+            result.add(role.getRoleName());
+        }
+
+        Collections.sort(result);
+        return result;
+    }
+
+    void createRoles(String ...roles) {
+        for (String role: roles) {
+            try {
+                sentryClient.createRole(authUser, role);
+            } catch (SentryUserException e) {
+                System.out.printf("failed to create role %s: %s\n",
+                        role, e.toString());
+            }
+        }
+    }
+
+    void removeRoles(String ...roles) {
+        for (String role: roles) {
+            try {
+                sentryClient.dropRole(authUser, role);
+            } catch (SentryUserException e) {
+                System.out.printf("failed to remove role %s: %s\n",
+                        role, e.toString());
+            }
+        }
+    }
+
+    List<String> listGroups() {
+        Set<TSentryRole> roles = null;
+
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error reading roles: " + e.toString());
+        }
+
+        if (roles == null || roles.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // Set of all group names
+        Set<String> groupNames = new HashSet<>();
+
+        // Get all group names
+        for (TSentryRole role: roles) {
+            for (TSentryGroup group: role.getGroups()) {
+                groupNames.add(group.getGroupName());
+            }
+        }
+
+        List<String> result = new ArrayList<>(groupNames);
+
+        Collections.sort(result);
+        return result;
+    }
+
+    List<String> listGroupRoles() {
+        Set<TSentryRole> roles = null;
+
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error reading roles: " + e.toString());
+        }
+
+        if (roles == null || roles.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // Set of all group names
+        Set<String> groupNames = new HashSet<>();
+
+        // Map group to set of roles
+        Map<String, Set<String>> groupInfo = new HashMap<>();
+
+        // Get all group names
+        for (TSentryRole role: roles) {
+            for (TSentryGroup group: role.getGroups()) {
+                String groupName = group.getGroupName();
+                groupNames.add(groupName);
+                Set<String> groupRoles = groupInfo.get(groupName);
+                if (groupRoles != null) {
+                    // Add a new or existing role
+                    groupRoles.add(role.getRoleName());
+                    continue;
+                }
+                // Never seen this group before
+                groupRoles = new HashSet<>();
+                groupRoles.add(role.getRoleName());
+                groupInfo.put(groupName, groupRoles);
+            }
+        }
+
+        List<String> groups = new ArrayList<>(groupNames);
+        Collections.sort(groups);
+
+        // Produce printable result as
+        // group1 = role1, role2, ...
+        // group2 = ...
+        List<String> result = new LinkedList<>();
+        for(String groupName: groups) {
+            result.add(groupName + " = " +
+                    StringUtils.join(groupInfo.get(groupName), ", "));
+        }
+        return result;
+    }
+
+    void grantGroupsToRole(String roleName, String ...groups) {
+        try {
+            sentryClient.grantRoleToGroups(authUser, roleName, Sets.newHashSet(groups));
+        } catch (SentryUserException e) {
+            System.out.printf("Failed to gran role %s to groups: %s\n",
+                    roleName, e.toString());
+        }
+    }
+
+    void revokeGroupsFromRole(String roleName, String ...groups) {
+        try {
+            sentryClient.revokeRoleFromGroups(authUser, roleName, Sets.newHashSet(groups));
+        } catch (SentryUserException e) {
+            System.out.printf("Failed to revoke role %s to groups: %s\n",
+                    roleName, e.toString());
+        }
+    }
+
+
+
+    ShellUtil(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.sentryClient = sentryClient;
+        this.authUser = authUser;
+    }
+
+    private final SentryPolicyServiceClient sentryClient;
+    private final String authUser;
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java
new file mode 100644
index 0000000..4bc7512
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java
@@ -0,0 +1,93 @@
+/**
+ * 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.sentry.provider.db.tools.cli;
+
+import com.budhash.cliche.*;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Top level commands
+ */
+public class TopLevelShell implements ShellDependent, Runnable {
+
+    private final Shell topShell;
+    private final ShellUtil tools;
+    private Shell shell; // top level shell object
+
+    private final String authUser;
+    private final SentryPolicyServiceClient sentryClient;
+
+    TopLevelShell(SentryPolicyServiceClient sentryClient,
+                  String authUser) {
+        this.authUser = authUser;
+        this.sentryClient = sentryClient;
+        this.tools = new ShellUtil(sentryClient, authUser);
+        topShell = ShellFactory.createConsoleShell("sentry",
+                "sentry shell\n" +
+                "Enter ?l to list available commands.",
+                this);
+    }
+
+    @Command(description="listRoles, create and remove roles")
+    public void roles() throws IOException {
+        ShellFactory.createSubshell("roles", shell, "roles commands",
+                new RolesShell(sentryClient, authUser)).commandLoop();
+    }
+
+    @Command(description = "listRoles, create and remove groups")
+    public void groups() throws IOException {
+        ShellFactory.createSubshell("groups", shell, "groups commands",
+                new GroupShell(sentryClient, authUser)).commandLoop();
+    }
+
+    @Command(description = "List sentry roles. shows all available roles.")
+    public List<String> listRoles() {
+        return tools.listRoles();
+    }
+
+    @Command(description = "List sentry roles by group")
+    public List<String> listRoles(
+            @Param(name = "groupName")
+            String group) {
+        return tools.listRoles(group);
+    }
+
+    @Command(abbrev = "lg", header = "[groups]",
+             description = "list groups and their roles")
+    public List<String> listGroups() {
+        return tools.listGroupRoles();
+    }
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+
+    @Override
+    public void run() {
+        try {
+            this.topShell.commandLoop();
+        } catch (IOException e) {
+            System.out.println("error: " + e.toString());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java
deleted file mode 100644
index fe4e52c..0000000
--- a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java
+++ /dev/null
@@ -1,65 +0,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.
- */
-
-package org.apache.sentry.provider.db.cli;
-
-import com.budhash.cliche.Command;
-import com.budhash.cliche.Shell;
-import com.budhash.cliche.ShellDependent;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-
-import java.util.List;
-
-/**
- * Sentry group manipulation for CLI
- */
-public class GroupShell implements ShellDependent {
-    @Command
-    public List<String> list() {
-        return tools.listGroups();
-    }
-
-    @Command(abbrev = "lr", header = "[groups]",
-            description = "list groups and their roles")
-    public List<String> listRoles() {
-        return tools.listGroupRoles();
-    }
-
-    @Command(description = "Grant role to groups")
-    public void grant(String roleName, String ...groups) {
-        tools.grantGroupsToRole(roleName, groups);
-    }
-
-    @Command(description = "Revoke role from groups")
-    public void revoke(String roleName, String ...groups) {
-        tools.revokeGroupsFromRole(roleName, groups);
-    }
-
-    private final ShellUtil tools;
-    Shell shell;
-
-
-    public GroupShell(SentryPolicyServiceClient sentryClient, String authUser) {
-        this.tools = new ShellUtil(sentryClient, authUser);
-    }
-
-    @Override
-    public void cliSetShell(Shell theShell) {
-        this.shell = theShell;
-    }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java
deleted file mode 100644
index fbd7ac0..0000000
--- a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java
+++ /dev/null
@@ -1,72 +0,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.
- */
-
-package org.apache.sentry.provider.db.cli;
-
-import com.budhash.cliche.Command;
-import com.budhash.cliche.Param;
-import com.budhash.cliche.Shell;
-import com.budhash.cliche.ShellDependent;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-
-import java.util.List;
-
-/**
- * Sentry roles manipulation for CLI.
- */
-public class RolesShell implements ShellDependent {
-    @Command(description = "List sentry roles. shows all available roles.")
-    public List<String> list() {
-        return tools.listRoles();
-    }
-
-    @Command(description = "List sentry roles by group")
-    public List<String> list(
-            @Param(name = "groupName", description = "group name for roles")
-            String group) {
-        return tools.listRoles(group);
-    }
-
-    @Command(description = "Create Sentry role(s).")
-    public void create(
-            @Param(name = "roleName", description = "name of role to create")
-            String ...roles) {
-        tools.createRoles(roles);
-    }
-
-    @Command(description = "remove Sentry role(s).")
-    public void remove(
-            @Param(name = "roleName ...", description = "role names to remove")
-            String ...roles) {
-        tools.removeRoles(roles);
-    }
-
-
-    @Override
-    public void cliSetShell(Shell theShell) {
-        this.shell = theShell;
-    }
-
-    private final ShellUtil tools;
-    Shell shell;
-
-    public RolesShell(SentryPolicyServiceClient sentryClient, String authUser) {
-        this.tools = new ShellUtil(sentryClient, authUser);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java
deleted file mode 100644
index 001397b..0000000
--- a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java
+++ /dev/null
@@ -1,172 +0,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.
- */
-
-package org.apache.sentry.provider.db.cli;
-
-import org.apache.commons.cli.*;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.service.thrift.SentryServiceClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
-
-/**
- * Sentry interactive tool
- */
-public class SentryCli {
-    private static final Logger log = LoggerFactory.getLogger(SentryCli.class.getName());
-    private static final String LOG4J_CONF = "log4jConf";
-    private final String[] args;
-    private Options options = new Options();
-    private CommandLine cmd;
-
-    private static final String configOpt = "config";
-    private static final String userOpt = "user";
-
-    private SentryPolicyServiceClient sentryClient;
-
-    public SentryPolicyServiceClient getSentryClient() {
-        return sentryClient;
-    }
-
-    public String getRequestorName() {
-        return requestorName;
-    }
-
-    private String requestorName;
-
-    public static void main(String[] args) {
-        SentryCli cli = new SentryCli(args);
-        // Create interactive shell and run it
-        TopLevelShell shell = new TopLevelShell(cli.getSentryClient(),
-                cli.getRequestorName());
-        shell.run();
-    }
-
-    /**
-     * Construct SentryCli from arguments
-     * @param args command-line arguments
-     */
-    public SentryCli(String[] args) {
-        this.args = args;
-        options.addOption("h", "help", false, "show help");
-        // file path of sentry-site
-        options.addOption("U", userOpt, true, "auth user");
-        options.addOption("c", configOpt, true, "sentry configuration");
-        options.addOption("L", LOG4J_CONF, true, "Location of log4j properties file");
-        CommandLineParser parser = new GnuParser();
-        try {
-            this.cmd = parser.parse(options, args);
-        } catch (ParseException e) {
-            help();
-        }
-        if (cmd.hasOption("h")) {
-            help();
-        }
-        init();
-    }
-
-    /**
-     * Parse command-line arguments.
-     */
-    public void parse() {
-        CommandLineParser parser = new GnuParser();
-        try {
-            cmd = parser.parse(options, args);
-            if (cmd.hasOption("h")) {
-                help();
-            }
-        } catch (ParseException e) {
-            log.warn("error in parsing expression", e);
-            help();
-            System.exit(1);
-        }
-    }
-
-    /**
-     * Initialize CLI
-     */
-    private void init() {
-        Map<String, String> env = System.getenv();
-        String pathConf = cmd.getOptionValue(configOpt);
-        if (pathConf == null) {
-            pathConf = env.get("SENTRY_CONFIG");
-        }
-        if (pathConf == null) {
-            System.out.println("Missing config file");
-            System.exit(1);
-        }
-
-        String log4jconf = cmd.getOptionValue(LOG4J_CONF);
-        if (log4jconf != null && log4jconf.length() > 0) {
-            Properties log4jProperties = new Properties();
-
-            // Firstly load log properties from properties file
-            FileInputStream istream = null;
-            try {
-                istream = new FileInputStream(log4jconf);
-            } catch (FileNotFoundException e) {
-                e.printStackTrace();
-            }
-            try {
-                log4jProperties.load(istream);
-                istream.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-
-            PropertyConfigurator.configure(log4jProperties);
-        }
-        Configuration conf = new Configuration();
-        conf.addResource(new Path(pathConf));
-
-        requestorName = cmd.getOptionValue(userOpt, "");
-        if (requestorName.isEmpty()) {
-            UserGroupInformation ugi = null;
-            try {
-                ugi = UserGroupInformation.getLoginUser();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            requestorName = ugi.getShortUserName();
-        }
-
-        try {
-            sentryClient = SentryServiceClientFactory.create(conf);
-        } catch (Exception e) {
-            System.out.println("Failed to connect to Sentry server: " + e.toString());
-        }
-    }
-
-    private void help() {
-        // This prints out some help
-        HelpFormatter formater = new HelpFormatter();
-        formater.printHelp("sentrycli", options);
-        System.exit(0);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java
deleted file mode 100644
index 95d8d4b..0000000
--- a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java
+++ /dev/null
@@ -1,205 +0,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.
- */
-
-package org.apache.sentry.provider.db.cli;
-
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
-import org.apache.sentry.provider.db.service.thrift.TSentryRole;
-
-import java.util.*;
-
-/**
- * ShellUtil implements actual commands
- */
-class ShellUtil {
-
-    List<String> listRoles() {
-        Set<TSentryRole> roles = null;
-        try {
-            roles = sentryClient.listRoles(authUser);
-        } catch (SentryUserException e) {
-            System.out.println("Error listing roles: " + e.toString());
-        }
-        List<String> result = new ArrayList<>();
-        if (roles == null || roles.isEmpty()) {
-            return result;
-        }
-
-        for(TSentryRole role: roles) {
-            result.add(role.getRoleName());
-        }
-
-        Collections.sort(result);
-        return result;
-    }
-
-    List<String> listRoles(String group) {
-        Set<TSentryRole> roles = null;
-        try {
-            roles = sentryClient.listRolesByGroupName(authUser, group);
-        } catch (SentryUserException e) {
-            System.out.println("Error listing roles: " + e.toString());
-        }
-        List<String> result = new ArrayList<>();
-        if (roles == null || roles.isEmpty()) {
-            return result;
-        }
-
-        for(TSentryRole role: roles) {
-            result.add(role.getRoleName());
-        }
-
-        Collections.sort(result);
-        return result;
-    }
-
-    void createRoles(String ...roles) {
-        for (String role: roles) {
-            try {
-                sentryClient.createRole(authUser, role);
-            } catch (SentryUserException e) {
-                System.out.printf("failed to create role %s: %s\n",
-                        role, e.toString());
-            }
-        }
-    }
-
-    void removeRoles(String ...roles) {
-        for (String role: roles) {
-            try {
-                sentryClient.dropRole(authUser, role);
-            } catch (SentryUserException e) {
-                System.out.printf("failed to remove role %s: %s\n",
-                        role, e.toString());
-            }
-        }
-    }
-
-    List<String> listGroups() {
-        Set<TSentryRole> roles = null;
-
-        try {
-            roles = sentryClient.listRoles(authUser);
-        } catch (SentryUserException e) {
-            System.out.println("Error reading roles: " + e.toString());
-        }
-
-        if (roles == null || roles.isEmpty()) {
-            return new ArrayList<>();
-        }
-
-        // Set of all group names
-        Set<String> groupNames = new HashSet<>();
-
-        // Get all group names
-        for (TSentryRole role: roles) {
-            for (TSentryGroup group: role.getGroups()) {
-                groupNames.add(group.getGroupName());
-            }
-        }
-
-        List<String> result = new ArrayList<>(groupNames);
-
-        Collections.sort(result);
-        return result;
-    }
-
-    List<String> listGroupRoles() {
-        Set<TSentryRole> roles = null;
-
-        try {
-            roles = sentryClient.listRoles(authUser);
-        } catch (SentryUserException e) {
-            System.out.println("Error reading roles: " + e.toString());
-        }
-
-        if (roles == null || roles.isEmpty()) {
-            return new ArrayList<>();
-        }
-
-        // Set of all group names
-        Set<String> groupNames = new HashSet<>();
-
-        // Map group to set of roles
-        Map<String, Set<String>> groupInfo = new HashMap<>();
-
-        // Get all group names
-        for (TSentryRole role: roles) {
-            for (TSentryGroup group: role.getGroups()) {
-                String groupName = group.getGroupName();
-                groupNames.add(groupName);
-                Set<String> groupRoles = groupInfo.get(groupName);
-                if (groupRoles != null) {
-                    // Add a new or existing role
-                    groupRoles.add(role.getRoleName());
-                    continue;
-                }
-                // Never seen this group before
-                groupRoles = new HashSet<>();
-                groupRoles.add(role.getRoleName());
-                groupInfo.put(groupName, groupRoles);
-            }
-        }
-
-        List<String> groups = new ArrayList<>(groupNames);
-        Collections.sort(groups);
-
-        // Produce printable result as
-        // group1 = role1, role2, ...
-        // group2 = ...
-        List<String> result = new LinkedList<>();
-        for(String groupName: groups) {
-            result.add(groupName + " = " +
-                    StringUtils.join(groupInfo.get(groupName), ", "));
-        }
-        return result;
-    }
-
-    void grantGroupsToRole(String roleName, String ...groups) {
-        try {
-            sentryClient.grantRoleToGroups(authUser, roleName, Sets.newHashSet(groups));
-        } catch (SentryUserException e) {
-            System.out.printf("Failed to gran role %s to groups: %s\n",
-                    roleName, e.toString());
-        }
-    }
-
-    void revokeGroupsFromRole(String roleName, String ...groups) {
-        try {
-            sentryClient.revokeRoleFromGroups(authUser, roleName, Sets.newHashSet(groups));
-        } catch (SentryUserException e) {
-            System.out.printf("Failed to revoke role %s to groups: %s\n",
-                    roleName, e.toString());
-        }
-    }
-
-
-
-    ShellUtil(SentryPolicyServiceClient sentryClient, String authUser) {
-        this.sentryClient = sentryClient;
-        this.authUser = authUser;
-    }
-
-    private final SentryPolicyServiceClient sentryClient;
-    private final String authUser;
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bc23df3f/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java
deleted file mode 100644
index f940e36..0000000
--- a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java
+++ /dev/null
@@ -1,93 +0,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.
- */
-
-package org.apache.sentry.provider.db.cli;
-
-import com.budhash.cliche.*;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Top level commands
- */
-public class TopLevelShell implements ShellDependent, Runnable {
-
-    private final Shell topShell;
-    private final ShellUtil tools;
-    private Shell shell; // top level shell object
-
-    private final String authUser;
-    private final SentryPolicyServiceClient sentryClient;
-
-    TopLevelShell(SentryPolicyServiceClient sentryClient,
-                  String authUser) {
-        this.authUser = authUser;
-        this.sentryClient = sentryClient;
-        this.tools = new ShellUtil(sentryClient, authUser);
-        topShell = ShellFactory.createConsoleShell("sentry",
-                "sentry shell\n" +
-                "Enter ?l to list available commands.",
-                this);
-    }
-
-    @Command(description="listRoles, create and remove roles")
-    public void roles() throws IOException {
-        ShellFactory.createSubshell("roles", shell, "roles commands",
-                new RolesShell(sentryClient, authUser)).commandLoop();
-    }
-
-    @Command(description = "listRoles, create and remove groups")
-    public void groups() throws IOException {
-        ShellFactory.createSubshell("groups", shell, "groups commands",
-                new GroupShell(sentryClient, authUser)).commandLoop();
-    }
-
-    @Command(description = "List sentry roles. shows all available roles.")
-    public List<String> listRoles() {
-        return tools.listRoles();
-    }
-
-    @Command(description = "List sentry roles by group")
-    public List<String> listRoles(
-            @Param(name = "groupName")
-            String group) {
-        return tools.listRoles(group);
-    }
-
-    @Command(abbrev = "lg", header = "[groups]",
-             description = "list groups and their roles")
-    public List<String> listGroups() {
-        return tools.listGroupRoles();
-    }
-
-    @Override
-    public void cliSetShell(Shell theShell) {
-        this.shell = theShell;
-    }
-
-    @Override
-    public void run() {
-        try {
-            this.topShell.commandLoop();
-        } catch (IOException e) {
-            System.out.println("error: " + e.toString());
-        }
-    }
-}


[05/12] sentry git commit: Initial version of interactive client shell

Posted by ak...@apache.org.
Initial version of interactive client shell


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

Branch: refs/heads/akolb-ha-cli
Commit: d7a183b1a5bdcd9c0c44418418253aa686ebaaa7
Parents: 9975ab2
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Mon Dec 12 12:57:32 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../sentry-binding-hive-follower/pom.xml        |   5 +
 .../sentry/provider/db/cli/GroupShell.java      |  65 ++++++
 .../sentry/provider/db/cli/RolesShell.java      |  72 +++++++
 .../sentry/provider/db/cli/SentryCli.java       | 172 ++++++++++++++++
 .../sentry/provider/db/cli/ShellUtil.java       | 205 +++++++++++++++++++
 .../sentry/provider/db/cli/TopLevelShell.java   |  93 +++++++++
 6 files changed, 612 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/d7a183b1/sentry-binding/sentry-binding-hive-follower/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive-follower/pom.xml b/sentry-binding/sentry-binding-hive-follower/pom.xml
index bcfb417..51bd482 100644
--- a/sentry-binding/sentry-binding-hive-follower/pom.xml
+++ b/sentry-binding/sentry-binding-hive-follower/pom.xml
@@ -66,6 +66,11 @@ limitations under the License.
       <version>${hive.version}</version>
       <scope>compile</scope>
     </dependency>
+    <dependency>
+      <groupId>com.budhash.cliche</groupId>
+      <artifactId>cliche-shell</artifactId>
+      <version>0.9.3</version>
+    </dependency>
   </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/sentry/blob/d7a183b1/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java
new file mode 100644
index 0000000..fe4e52c
--- /dev/null
+++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/GroupShell.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.sentry.provider.db.cli;
+
+import com.budhash.cliche.Command;
+import com.budhash.cliche.Shell;
+import com.budhash.cliche.ShellDependent;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.util.List;
+
+/**
+ * Sentry group manipulation for CLI
+ */
+public class GroupShell implements ShellDependent {
+    @Command
+    public List<String> list() {
+        return tools.listGroups();
+    }
+
+    @Command(abbrev = "lr", header = "[groups]",
+            description = "list groups and their roles")
+    public List<String> listRoles() {
+        return tools.listGroupRoles();
+    }
+
+    @Command(description = "Grant role to groups")
+    public void grant(String roleName, String ...groups) {
+        tools.grantGroupsToRole(roleName, groups);
+    }
+
+    @Command(description = "Revoke role from groups")
+    public void revoke(String roleName, String ...groups) {
+        tools.revokeGroupsFromRole(roleName, groups);
+    }
+
+    private final ShellUtil tools;
+    Shell shell;
+
+
+    public GroupShell(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.tools = new ShellUtil(sentryClient, authUser);
+    }
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d7a183b1/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java
new file mode 100644
index 0000000..fbd7ac0
--- /dev/null
+++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/RolesShell.java
@@ -0,0 +1,72 @@
+/*
+ * 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.sentry.provider.db.cli;
+
+import com.budhash.cliche.Command;
+import com.budhash.cliche.Param;
+import com.budhash.cliche.Shell;
+import com.budhash.cliche.ShellDependent;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.util.List;
+
+/**
+ * Sentry roles manipulation for CLI.
+ */
+public class RolesShell implements ShellDependent {
+    @Command(description = "List sentry roles. shows all available roles.")
+    public List<String> list() {
+        return tools.listRoles();
+    }
+
+    @Command(description = "List sentry roles by group")
+    public List<String> list(
+            @Param(name = "groupName", description = "group name for roles")
+            String group) {
+        return tools.listRoles(group);
+    }
+
+    @Command(description = "Create Sentry role(s).")
+    public void create(
+            @Param(name = "roleName", description = "name of role to create")
+            String ...roles) {
+        tools.createRoles(roles);
+    }
+
+    @Command(description = "remove Sentry role(s).")
+    public void remove(
+            @Param(name = "roleName ...", description = "role names to remove")
+            String ...roles) {
+        tools.removeRoles(roles);
+    }
+
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+
+    private final ShellUtil tools;
+    Shell shell;
+
+    public RolesShell(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.tools = new ShellUtil(sentryClient, authUser);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d7a183b1/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java
new file mode 100644
index 0000000..001397b
--- /dev/null
+++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/SentryCli.java
@@ -0,0 +1,172 @@
+/**
+ * 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.sentry.provider.db.cli;
+
+import org.apache.commons.cli.*;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.service.thrift.SentryServiceClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Sentry interactive tool
+ */
+public class SentryCli {
+    private static final Logger log = LoggerFactory.getLogger(SentryCli.class.getName());
+    private static final String LOG4J_CONF = "log4jConf";
+    private final String[] args;
+    private Options options = new Options();
+    private CommandLine cmd;
+
+    private static final String configOpt = "config";
+    private static final String userOpt = "user";
+
+    private SentryPolicyServiceClient sentryClient;
+
+    public SentryPolicyServiceClient getSentryClient() {
+        return sentryClient;
+    }
+
+    public String getRequestorName() {
+        return requestorName;
+    }
+
+    private String requestorName;
+
+    public static void main(String[] args) {
+        SentryCli cli = new SentryCli(args);
+        // Create interactive shell and run it
+        TopLevelShell shell = new TopLevelShell(cli.getSentryClient(),
+                cli.getRequestorName());
+        shell.run();
+    }
+
+    /**
+     * Construct SentryCli from arguments
+     * @param args command-line arguments
+     */
+    public SentryCli(String[] args) {
+        this.args = args;
+        options.addOption("h", "help", false, "show help");
+        // file path of sentry-site
+        options.addOption("U", userOpt, true, "auth user");
+        options.addOption("c", configOpt, true, "sentry configuration");
+        options.addOption("L", LOG4J_CONF, true, "Location of log4j properties file");
+        CommandLineParser parser = new GnuParser();
+        try {
+            this.cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            help();
+        }
+        if (cmd.hasOption("h")) {
+            help();
+        }
+        init();
+    }
+
+    /**
+     * Parse command-line arguments.
+     */
+    public void parse() {
+        CommandLineParser parser = new GnuParser();
+        try {
+            cmd = parser.parse(options, args);
+            if (cmd.hasOption("h")) {
+                help();
+            }
+        } catch (ParseException e) {
+            log.warn("error in parsing expression", e);
+            help();
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Initialize CLI
+     */
+    private void init() {
+        Map<String, String> env = System.getenv();
+        String pathConf = cmd.getOptionValue(configOpt);
+        if (pathConf == null) {
+            pathConf = env.get("SENTRY_CONFIG");
+        }
+        if (pathConf == null) {
+            System.out.println("Missing config file");
+            System.exit(1);
+        }
+
+        String log4jconf = cmd.getOptionValue(LOG4J_CONF);
+        if (log4jconf != null && log4jconf.length() > 0) {
+            Properties log4jProperties = new Properties();
+
+            // Firstly load log properties from properties file
+            FileInputStream istream = null;
+            try {
+                istream = new FileInputStream(log4jconf);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+            try {
+                log4jProperties.load(istream);
+                istream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            PropertyConfigurator.configure(log4jProperties);
+        }
+        Configuration conf = new Configuration();
+        conf.addResource(new Path(pathConf));
+
+        requestorName = cmd.getOptionValue(userOpt, "");
+        if (requestorName.isEmpty()) {
+            UserGroupInformation ugi = null;
+            try {
+                ugi = UserGroupInformation.getLoginUser();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            requestorName = ugi.getShortUserName();
+        }
+
+        try {
+            sentryClient = SentryServiceClientFactory.create(conf);
+        } catch (Exception e) {
+            System.out.println("Failed to connect to Sentry server: " + e.toString());
+        }
+    }
+
+    private void help() {
+        // This prints out some help
+        HelpFormatter formater = new HelpFormatter();
+        formater.printHelp("sentrycli", options);
+        System.exit(0);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d7a183b1/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java
new file mode 100644
index 0000000..95d8d4b
--- /dev/null
+++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/ShellUtil.java
@@ -0,0 +1,205 @@
+/*
+ * 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.sentry.provider.db.cli;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+
+import java.util.*;
+
+/**
+ * ShellUtil implements actual commands
+ */
+class ShellUtil {
+
+    List<String> listRoles() {
+        Set<TSentryRole> roles = null;
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error listing roles: " + e.toString());
+        }
+        List<String> result = new ArrayList<>();
+        if (roles == null || roles.isEmpty()) {
+            return result;
+        }
+
+        for(TSentryRole role: roles) {
+            result.add(role.getRoleName());
+        }
+
+        Collections.sort(result);
+        return result;
+    }
+
+    List<String> listRoles(String group) {
+        Set<TSentryRole> roles = null;
+        try {
+            roles = sentryClient.listRolesByGroupName(authUser, group);
+        } catch (SentryUserException e) {
+            System.out.println("Error listing roles: " + e.toString());
+        }
+        List<String> result = new ArrayList<>();
+        if (roles == null || roles.isEmpty()) {
+            return result;
+        }
+
+        for(TSentryRole role: roles) {
+            result.add(role.getRoleName());
+        }
+
+        Collections.sort(result);
+        return result;
+    }
+
+    void createRoles(String ...roles) {
+        for (String role: roles) {
+            try {
+                sentryClient.createRole(authUser, role);
+            } catch (SentryUserException e) {
+                System.out.printf("failed to create role %s: %s\n",
+                        role, e.toString());
+            }
+        }
+    }
+
+    void removeRoles(String ...roles) {
+        for (String role: roles) {
+            try {
+                sentryClient.dropRole(authUser, role);
+            } catch (SentryUserException e) {
+                System.out.printf("failed to remove role %s: %s\n",
+                        role, e.toString());
+            }
+        }
+    }
+
+    List<String> listGroups() {
+        Set<TSentryRole> roles = null;
+
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error reading roles: " + e.toString());
+        }
+
+        if (roles == null || roles.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // Set of all group names
+        Set<String> groupNames = new HashSet<>();
+
+        // Get all group names
+        for (TSentryRole role: roles) {
+            for (TSentryGroup group: role.getGroups()) {
+                groupNames.add(group.getGroupName());
+            }
+        }
+
+        List<String> result = new ArrayList<>(groupNames);
+
+        Collections.sort(result);
+        return result;
+    }
+
+    List<String> listGroupRoles() {
+        Set<TSentryRole> roles = null;
+
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error reading roles: " + e.toString());
+        }
+
+        if (roles == null || roles.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // Set of all group names
+        Set<String> groupNames = new HashSet<>();
+
+        // Map group to set of roles
+        Map<String, Set<String>> groupInfo = new HashMap<>();
+
+        // Get all group names
+        for (TSentryRole role: roles) {
+            for (TSentryGroup group: role.getGroups()) {
+                String groupName = group.getGroupName();
+                groupNames.add(groupName);
+                Set<String> groupRoles = groupInfo.get(groupName);
+                if (groupRoles != null) {
+                    // Add a new or existing role
+                    groupRoles.add(role.getRoleName());
+                    continue;
+                }
+                // Never seen this group before
+                groupRoles = new HashSet<>();
+                groupRoles.add(role.getRoleName());
+                groupInfo.put(groupName, groupRoles);
+            }
+        }
+
+        List<String> groups = new ArrayList<>(groupNames);
+        Collections.sort(groups);
+
+        // Produce printable result as
+        // group1 = role1, role2, ...
+        // group2 = ...
+        List<String> result = new LinkedList<>();
+        for(String groupName: groups) {
+            result.add(groupName + " = " +
+                    StringUtils.join(groupInfo.get(groupName), ", "));
+        }
+        return result;
+    }
+
+    void grantGroupsToRole(String roleName, String ...groups) {
+        try {
+            sentryClient.grantRoleToGroups(authUser, roleName, Sets.newHashSet(groups));
+        } catch (SentryUserException e) {
+            System.out.printf("Failed to gran role %s to groups: %s\n",
+                    roleName, e.toString());
+        }
+    }
+
+    void revokeGroupsFromRole(String roleName, String ...groups) {
+        try {
+            sentryClient.revokeRoleFromGroups(authUser, roleName, Sets.newHashSet(groups));
+        } catch (SentryUserException e) {
+            System.out.printf("Failed to revoke role %s to groups: %s\n",
+                    roleName, e.toString());
+        }
+    }
+
+
+
+    ShellUtil(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.sentryClient = sentryClient;
+        this.authUser = authUser;
+    }
+
+    private final SentryPolicyServiceClient sentryClient;
+    private final String authUser;
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d7a183b1/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java
new file mode 100644
index 0000000..f940e36
--- /dev/null
+++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/cli/TopLevelShell.java
@@ -0,0 +1,93 @@
+/**
+ * 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.sentry.provider.db.cli;
+
+import com.budhash.cliche.*;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Top level commands
+ */
+public class TopLevelShell implements ShellDependent, Runnable {
+
+    private final Shell topShell;
+    private final ShellUtil tools;
+    private Shell shell; // top level shell object
+
+    private final String authUser;
+    private final SentryPolicyServiceClient sentryClient;
+
+    TopLevelShell(SentryPolicyServiceClient sentryClient,
+                  String authUser) {
+        this.authUser = authUser;
+        this.sentryClient = sentryClient;
+        this.tools = new ShellUtil(sentryClient, authUser);
+        topShell = ShellFactory.createConsoleShell("sentry",
+                "sentry shell\n" +
+                "Enter ?l to list available commands.",
+                this);
+    }
+
+    @Command(description="listRoles, create and remove roles")
+    public void roles() throws IOException {
+        ShellFactory.createSubshell("roles", shell, "roles commands",
+                new RolesShell(sentryClient, authUser)).commandLoop();
+    }
+
+    @Command(description = "listRoles, create and remove groups")
+    public void groups() throws IOException {
+        ShellFactory.createSubshell("groups", shell, "groups commands",
+                new GroupShell(sentryClient, authUser)).commandLoop();
+    }
+
+    @Command(description = "List sentry roles. shows all available roles.")
+    public List<String> listRoles() {
+        return tools.listRoles();
+    }
+
+    @Command(description = "List sentry roles by group")
+    public List<String> listRoles(
+            @Param(name = "groupName")
+            String group) {
+        return tools.listRoles(group);
+    }
+
+    @Command(abbrev = "lg", header = "[groups]",
+             description = "list groups and their roles")
+    public List<String> listGroups() {
+        return tools.listGroupRoles();
+    }
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+
+    @Override
+    public void run() {
+        try {
+            this.topShell.commandLoop();
+        } catch (IOException e) {
+            System.out.println("error: " + e.toString());
+        }
+    }
+}


[02/12] sentry git commit: Added command documentation

Posted by ak...@apache.org.
Added command documentation


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/25fbdb9d
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/25fbdb9d
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/25fbdb9d

Branch: refs/heads/akolb-ha-cli
Commit: 25fbdb9de5e5823291bf63f856c36c2f5d27a276
Parents: 250cf9f
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Wed Dec 14 12:50:36 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../org/apache/sentry/shell/PrivsShell.java     | 19 +++++++++++---
 .../java/org/apache/sentry/shell/ShellUtil.java |  3 +++
 .../org/apache/sentry/shell/TopLevelShell.java  | 27 ++++++++++++++++----
 3 files changed, 41 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/25fbdb9d/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
index 82369cd..9d8b9d9 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
@@ -19,6 +19,7 @@
 package org.apache.sentry.shell;
 
 import com.budhash.cliche.Command;
+import com.budhash.cliche.Param;
 import com.budhash.cliche.Shell;
 import com.budhash.cliche.ShellDependent;
 import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
@@ -30,7 +31,12 @@ public class PrivsShell implements ShellDependent {
     Shell shell;
 
     @Command(description = "Grant privilege to role")
-    public void grant(String roleName, String privilege) {
+    public void grant(
+            @Param(name = "roleName")
+            String roleName,
+            @Param(name = "privilege",
+                    description = "privilege string, e.g. server=s1->db=foo")
+            String privilege) {
         tools.grantPrivilegeToRole(roleName, privilege);
     }
 
@@ -40,12 +46,19 @@ public class PrivsShell implements ShellDependent {
     }
 
     @Command
-    public List<String> list(String roleName) {
+    public List<String> list(
+            @Param(name = "roleName")
+            String roleName) {
         return tools.listPrivileges(roleName);
     }
 
     @Command
-    public void revoke(String roleName, String privilege) {
+    public void revoke(
+            @Param(name = "roleName")
+            String roleName,
+            @Param(name = "privilege",
+                    description = "privilege string, e.g. server=s1->db=foo")
+            String privilege) {
         tools.revokePrivilegeFromRole(roleName, privilege);
     }
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/25fbdb9d/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
index 4decf28..007975c 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
@@ -236,6 +236,9 @@ class ShellUtil {
         List<String> result = new LinkedList<>();
         for (TSentryPrivilege privilege : privileges) {
             String privilegeStr =  convertTSentryPrivilegeToStr(privilege);
+            if (privilegeStr.isEmpty()) {
+                continue;
+            }
             result.add(privilegeStr);
         }
         return result;

http://git-wip-us.apache.org/repos/asf/sentry/blob/25fbdb9d/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index d5d74b4..ef5313a 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -84,13 +84,20 @@ public class TopLevelShell implements ShellDependent, Runnable {
     }
 
     @Command(description = "Grant role to groups")
-    public void grantRole(String roleName, String ...groups) {
+    public void grantRole(
+            @Param(name = "roleName")
+            String roleName,
+            @Param(name = "group...") String ...groups) {
         tools.grantGroupsToRole(roleName, groups);
     }
 
     @Command(abbrev = "grm",
             description = "Revoke role from groups")
-    public void revokeRole(String roleName, String ...groups) {
+    public void revokeRole(
+            @Param(name = "roleName")
+            String roleName,
+            @Param(name = "group...")
+            String ...groups) {
         tools.revokeGroupsFromRole(roleName, groups);
     }
 
@@ -114,17 +121,27 @@ public class TopLevelShell implements ShellDependent, Runnable {
     }
 
     @Command(description = "list Sentry privileges")
-    public List<String> listPrivileges(String roleName) {
+    public List<String> listPrivileges(
+            @Param(name = "roleName")
+            String roleName) {
         return tools.listPrivileges(roleName);
     }
 
     @Command(description = "Grant privilege to role")
-    public void grantPrivilege(String roleName, String privilege) {
+    public void grantPrivilege(
+            @Param(name = "roleName")
+            String roleName,
+            @Param(name = "privilege", description = "privilege string, e.g. server=s1->db=foo")
+            String privilege) {
         tools.grantPrivilegeToRole(roleName, privilege);
     }
 
     @Command
-    public void revokePrivilege(String roleName, String privilege) {
+    public void revokePrivilege(
+            @Param(name = "roleName")
+            String roleName,
+            @Param(name = "privilege", description = "privilege string, e.g. server=s1->db=foo")
+            String privilege) {
         tools.revokePrivilegeFromRole(roleName, privilege);
     }
 


[03/12] sentry git commit: Added some privilege commands

Posted by ak...@apache.org.
Added some privilege commands


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

Branch: refs/heads/akolb-ha-cli
Commit: f8cc8eab17073d6e0d36b9c41e2fa6763b0b9b8f
Parents: fec2f86
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Tue Dec 13 16:26:08 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 pom.xml                                         |  1 +
 .../service/thrift/SentryServiceUtil.java       |  2 +-
 .../org/apache/sentry/shell/PrivsShell.java     | 51 ++++++++++++++++
 .../java/org/apache/sentry/shell/ShellUtil.java | 64 +++++++++++++++++++-
 .../org/apache/sentry/shell/TopLevelShell.java  | 10 ++-
 5 files changed, 122 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/f8cc8eab/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index b9282e7..ba922ea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -627,6 +627,7 @@ limitations under the License.
     <module>sentry-hdfs</module>
     <module>sentry-solr</module>
     <module>sentry-dist</module>
+    <module>sentry-tools</module>
   </modules>
 
   <build>

http://git-wip-us.apache.org/repos/asf/sentry/blob/f8cc8eab/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
index ce73358..1dd90f2 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
@@ -37,7 +37,7 @@ public final class SentryServiceUtil {
   // parse the privilege in String and get the TSentryPrivilege as result
   public static TSentryPrivilege convertToTSentryPrivilege(String privilegeStr) {
     TSentryPrivilege tSentryPrivilege = new TSentryPrivilege();
-    for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.split(privilegeStr)) {
+     for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.split(privilegeStr)) {
       KeyValue tempKV = new KeyValue(authorizable);
       String key = tempKV.getKey();
       String value = tempKV.getValue();

http://git-wip-us.apache.org/repos/asf/sentry/blob/f8cc8eab/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
new file mode 100644
index 0000000..cf2ebbd
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
@@ -0,0 +1,51 @@
+/*
+ * 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.sentry.shell;
+
+import com.budhash.cliche.Command;
+import com.budhash.cliche.Shell;
+import com.budhash.cliche.ShellDependent;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.util.List;
+
+public class PrivsShell implements ShellDependent {
+    private final ShellUtil tools;
+    Shell shell;
+
+    @Command(description = "Grant privilege to role")
+    public void grant(String roleName, String privilege) {
+        tools.grantPrivilegeToRole(roleName, privilege);
+    }
+
+    @Command
+    public List<String> list(String roleName) {
+        return tools.listPrivileges(roleName);
+    }
+
+
+    public PrivsShell(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.tools = new ShellUtil(sentryClient, authUser);
+    }
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/f8cc8eab/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
index a062c12..fbd382a 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
@@ -21,12 +21,15 @@ package org.apache.sentry.shell;
 import com.google.common.collect.Sets;
 import org.apache.commons.lang.StringUtils;
 import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
-import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+import org.apache.sentry.provider.db.service.thrift.*;
+import org.apache.sentry.service.thrift.SentryServiceUtil;
+import org.apache.sentry.service.thrift.ServiceConstants;
 
 import java.util.*;
 
+import static org.apache.sentry.service.thrift.SentryServiceUtil.convertTSentryPrivilegeToStr;
+import static org.apache.sentry.service.thrift.SentryServiceUtil.convertToTSentryPrivilege;
+
 /**
  * ShellUtil implements actual commands
  */
@@ -192,7 +195,62 @@ class ShellUtil {
         }
     }
 
+    void grantPrivilegeToRole(String roleName, String privilege) {
+        TSentryPrivilege tPriv = convertToTSentryPrivilege(privilege);
+        boolean grantOption = tPriv.getGrantOption().equals(TSentryGrantOption.TRUE);
+        try {
+            if (ServiceConstants.PrivilegeScope.SERVER.toString().equals(tPriv.getPrivilegeScope())) {
+                sentryClient.grantServerPrivilege(authUser, roleName, tPriv.getServerName(),
+                        tPriv.getAction(), grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.DATABASE.toString().equals(tPriv.getPrivilegeScope())) {
+                sentryClient.grantDatabasePrivilege(authUser, roleName, tPriv.getServerName(),
+                        tPriv.getDbName(), tPriv.getAction(), grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.TABLE.toString().equals(tPriv.getPrivilegeScope())) {
+                sentryClient.grantTablePrivilege(authUser, roleName, tPriv.getServerName(),
+                        tPriv.getDbName(), tPriv.getTableName(),
+                        tPriv.getAction(), grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.COLUMN.toString().equals(tPriv.getPrivilegeScope())) {
+                sentryClient.grantColumnPrivilege(authUser, roleName, tPriv.getServerName(),
+                        tPriv.getDbName(), tPriv.getTableName(),
+                        tPriv.getColumnName(), tPriv.getAction(), grantOption);
+                return;
+            }
+            if (ServiceConstants.PrivilegeScope.URI.toString().equals(tPriv.getPrivilegeScope())) {
+                sentryClient.grantURIPrivilege(authUser, roleName, tPriv.getServerName(),
+                        tPriv.getURI(), grantOption);
+                return;
+            }
+        } catch (SentryUserException e) {
+            System.out.println("Error granting privilege: " + e.toString());
+        }
+    }
 
+    List<String> listPrivileges(String roleName) {
+        Set<TSentryPrivilege> privileges = null;
+        try {
+            privileges = sentryClient
+                    .listAllPrivilegesByRoleName(authUser, roleName);
+        } catch (SentryUserException e) {
+            System.out.println("Failed to list privileges: " + e.toString());
+        }
+
+        if (privileges == null || privileges.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        List<String> result = new LinkedList<>();
+        for (TSentryPrivilege privilege : privileges) {
+            String privilegeStr =  convertTSentryPrivilegeToStr(privilege);
+            result.add(privilegeStr);
+        }
+        return result;
+    }
 
     ShellUtil(SentryPolicyServiceClient sentryClient, String authUser) {
         this.sentryClient = sentryClient;

http://git-wip-us.apache.org/repos/asf/sentry/blob/f8cc8eab/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index b2b7e8d..b677f0f 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -47,18 +47,24 @@ public class TopLevelShell implements ShellDependent, Runnable {
                 this);
     }
 
-    @Command(description="listRoles, create and remove roles")
+    @Command(description="list, create and remove roles")
     public void roles() throws IOException {
         ShellFactory.createSubshell("roles", shell, "roles commands",
                 new RolesShell(sentryClient, authUser)).commandLoop();
     }
 
-    @Command(description = "listRoles, create and remove groups")
+    @Command(description = "list, create and remove groups")
     public void groups() throws IOException {
         ShellFactory.createSubshell("groups", shell, "groups commands",
                 new GroupShell(sentryClient, authUser)).commandLoop();
     }
 
+    @Command(description = "list, create and remove privileges")
+    public void privileges() throws IOException {
+        ShellFactory.createSubshell("privileges", shell, "privileges commands",
+                new PrivsShell(sentryClient, authUser)).commandLoop();
+    }
+
     @Command(description = "List sentry roles. shows all available roles.")
     public List<String> listRoles() {
         return tools.listRoles();


[12/12] sentry git commit: Get host from environment or cmdline

Posted by ak...@apache.org.
Get host from environment or cmdline


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/250cf9fe
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/250cf9fe
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/250cf9fe

Branch: refs/heads/akolb-ha-cli
Commit: 250cf9fea775614069f4b542df4c76d943f96e7b
Parents: f2ab8cb
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Tue Dec 13 20:03:25 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../java/org/apache/sentry/shell/SentryCli.java | 57 +++++++++++++++-----
 1 file changed, 45 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/250cf9fe/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
index 61dcc04..180d240 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
@@ -34,6 +34,10 @@ import java.io.IOException;
 import java.util.Map;
 import java.util.Properties;
 
+import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVER_RPC_ADDRESS;
+import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SECURITY_MODE;
+import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SECURITY_MODE_NONE;
+
 /**
  * Sentry interactive tool
  */
@@ -44,8 +48,18 @@ public class SentryCli {
     private Options options = new Options();
     private CommandLine cmd;
 
+    private static final String localhost = "localhost";
+    private static final String defaultPort = "8038";
+
+
     private static final String configOpt = "config";
     private static final String userOpt = "user";
+    private static final String hostOpt = "host";
+
+    private static final String configEnv = "SENTRY_CONFIG";
+    private static final String hostEnv = "SENTRY_HOST";
+    private static final String userEnv = "SENTRY_USER";
+
 
     private SentryPolicyServiceClient sentryClient;
 
@@ -76,6 +90,7 @@ public class SentryCli {
         options.addOption("h", "help", false, "show help");
         // file path of sentry-site
         options.addOption("U", userOpt, true, "auth user");
+        options.addOption("H", hostOpt, true, "host address");
         options.addOption("c", configOpt, true, "sentry configuration");
         options.addOption("L", LOG4J_CONF, true, "Location of log4j properties file");
         CommandLineParser parser = new GnuParser();
@@ -112,15 +127,6 @@ public class SentryCli {
      */
     private void init() {
         Map<String, String> env = System.getenv();
-        String pathConf = cmd.getOptionValue(configOpt);
-        if (pathConf == null) {
-            pathConf = env.get("SENTRY_CONFIG");
-        }
-        if (pathConf == null) {
-            System.out.println("Missing config file");
-            System.exit(1);
-        }
-
         String log4jconf = cmd.getOptionValue(LOG4J_CONF);
         if (log4jconf != null && log4jconf.length() > 0) {
             Properties log4jProperties = new Properties();
@@ -141,11 +147,38 @@ public class SentryCli {
 
             PropertyConfigurator.configure(log4jProperties);
         }
+
+        String host = cmd.getOptionValue(hostOpt);
+        if (host == null) {
+            host = env.get(hostEnv);
+        }
+
+        String pathConf = cmd.getOptionValue(configOpt);
+        if (pathConf == null) {
+            pathConf = env.get(configEnv);
+        }
+        if (host == null && pathConf == null) {
+            host = localhost + ":" + defaultPort;
+        }
+
         Configuration conf = new Configuration();
-        conf.addResource(new Path(pathConf));
 
-        requestorName = cmd.getOptionValue(userOpt, "");
-        if (requestorName.isEmpty()) {
+        if (pathConf != null) {
+            conf.addResource(new Path(pathConf));
+        } else {
+            conf.set(SECURITY_MODE, SECURITY_MODE_NONE);
+        }
+
+        if (host != null) {
+            conf.set(SERVER_RPC_ADDRESS, host);
+        }
+
+        requestorName = cmd.getOptionValue(userOpt);
+        if (requestorName == null) {
+            requestorName = env.get(userEnv);
+        }
+        if (requestorName == null) {
+
             UserGroupInformation ugi = null;
             try {
                 ugi = UserGroupInformation.getLoginUser();


[09/12] sentry git commit: move group commands to top level.

Posted by ak...@apache.org.
move group commands to top level.


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

Branch: refs/heads/akolb-ha-cli
Commit: fec2f86c913d414651c5468983a0e66fb6bc8db4
Parents: 861ba6f
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Mon Dec 12 18:36:44 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../org/apache/sentry/shell/TopLevelShell.java  | 25 ++++++++++++++++++++
 1 file changed, 25 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/fec2f86c/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index c1d8a77..b2b7e8d 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -77,6 +77,31 @@ public class TopLevelShell implements ShellDependent, Runnable {
         return tools.listGroupRoles();
     }
 
+    @Command(description = "Grant role to groups")
+    public void grantRole(String roleName, String ...groups) {
+        tools.grantGroupsToRole(roleName, groups);
+    }
+
+    @Command(abbrev = "grm",
+            description = "Revoke role from groups")
+    public void revokeRole(String roleName, String ...groups) {
+        tools.revokeGroupsFromRole(roleName, groups);
+    }
+
+    @Command(description = "Create Sentry role(s).")
+    public void createRole(
+            @Param(name = "roleName", description = "name of role to create")
+                    String ...roles) {
+        tools.createRoles(roles);
+    }
+
+    @Command(abbrev = "rm", description = "remove Sentry role(s).")
+    public void removeRole(
+            @Param(name = "roleName ...", description = "role names to remove")
+                    String ...roles) {
+        tools.removeRoles(roles);
+    }
+
     @Override
     public void cliSetShell(Shell theShell) {
         this.shell = theShell;


[04/12] sentry git commit: mysql dependency

Posted by ak...@apache.org.
mysql dependency


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/9975ab26
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/9975ab26
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/9975ab26

Branch: refs/heads/akolb-ha-cli
Commit: 9975ab2674683bfb63be75c9e84df55db9f98f7a
Parents: 91168c6
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Mon Dec 12 12:56:38 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 sentry-dist/pom.xml | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/9975ab26/sentry-dist/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-dist/pom.xml b/sentry-dist/pom.xml
index 5952b87..14f6ba1 100644
--- a/sentry-dist/pom.xml
+++ b/sentry-dist/pom.xml
@@ -98,6 +98,11 @@ limitations under the License.
       <groupId>org.apache.sentry</groupId>
       <artifactId>sentry-hdfs-dist</artifactId>
     </dependency>
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+      <version>5.1.39</version>
+    </dependency>
   </dependencies>
   <profiles>
     <profile>


[11/12] sentry git commit: Help strings cleanup

Posted by ak...@apache.org.
Help strings cleanup


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/6ae74f32
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/6ae74f32
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/6ae74f32

Branch: refs/heads/akolb-ha-cli
Commit: 6ae74f32aadc370c7be27f554806dfd3d286cf28
Parents: 25fbdb9
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Thu Dec 15 16:20:23 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../java/org/apache/sentry/shell/GroupShell.java    |  9 +++++++--
 .../java/org/apache/sentry/shell/PrivsShell.java    |  6 ++----
 .../java/org/apache/sentry/shell/SentryCli.java     |  4 +++-
 .../java/org/apache/sentry/shell/TopLevelShell.java | 16 ++++++----------
 4 files changed, 18 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/6ae74f32/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
index 3fc7a31..246509c 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
@@ -19,6 +19,7 @@
 package org.apache.sentry.shell;
 
 import com.budhash.cliche.Command;
+import com.budhash.cliche.Param;
 import com.budhash.cliche.Shell;
 import com.budhash.cliche.ShellDependent;
 import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
@@ -41,12 +42,16 @@ public class GroupShell implements ShellDependent {
     }
 
     @Command(description = "Grant role to groups")
-    public void grant(String roleName, String ...groups) {
+    public void grant(
+            @Param(name = "roleName") String roleName,
+            @Param(name = "group") String ...groups) {
         tools.grantGroupsToRole(roleName, groups);
     }
 
     @Command(description = "Revoke role from groups")
-    public void revoke(String roleName, String ...groups) {
+    public void revoke(
+            @Param(name = "roleName") String roleName,
+            @Param(name = "group") String ...groups) {
         tools.revokeGroupsFromRole(roleName, groups);
     }
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/6ae74f32/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
index 9d8b9d9..2e12be8 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
@@ -47,15 +47,13 @@ public class PrivsShell implements ShellDependent {
 
     @Command
     public List<String> list(
-            @Param(name = "roleName")
-            String roleName) {
+            @Param(name = "roleName") String roleName) {
         return tools.listPrivileges(roleName);
     }
 
     @Command
     public void revoke(
-            @Param(name = "roleName")
-            String roleName,
+            @Param(name = "roleName") String roleName,
             @Param(name = "privilege",
                     description = "privilege string, e.g. server=s1->db=foo")
             String privilege) {

http://git-wip-us.apache.org/repos/asf/sentry/blob/6ae74f32/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
index 180d240..36833c8 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
@@ -142,7 +142,7 @@ public class SentryCli {
                 log4jProperties.load(istream);
                 istream.close();
             } catch (IOException e) {
-                e.printStackTrace();
+                System.out.println(e.toString());
             }
 
             PropertyConfigurator.configure(log4jProperties);
@@ -170,6 +170,7 @@ public class SentryCli {
         }
 
         if (host != null) {
+            System.out.println("Connecting to " + host);
             conf.set(SERVER_RPC_ADDRESS, host);
         }
 
@@ -192,6 +193,7 @@ public class SentryCli {
             sentryClient = SentryServiceClientFactory.create(conf);
         } catch (Exception e) {
             System.out.println("Failed to connect to Sentry server: " + e.toString());
+            e.printStackTrace();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/6ae74f32/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index ef5313a..047f11c 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -72,8 +72,7 @@ public class TopLevelShell implements ShellDependent, Runnable {
 
     @Command(description = "List sentry roles by group")
     public List<String> listRoles(
-            @Param(name = "groupName")
-            String group) {
+            @Param(name = "groupName") String group) {
         return tools.listRoles(group);
     }
 
@@ -85,19 +84,16 @@ public class TopLevelShell implements ShellDependent, Runnable {
 
     @Command(description = "Grant role to groups")
     public void grantRole(
-            @Param(name = "roleName")
-            String roleName,
-            @Param(name = "group...") String ...groups) {
+            @Param(name = "roleName") String roleName,
+            @Param(name = "group") String ...groups) {
         tools.grantGroupsToRole(roleName, groups);
     }
 
     @Command(abbrev = "grm",
             description = "Revoke role from groups")
     public void revokeRole(
-            @Param(name = "roleName")
-            String roleName,
-            @Param(name = "group...")
-            String ...groups) {
+            @Param(name = "roleName") String roleName,
+            @Param(name = "group") String ...groups) {
         tools.revokeGroupsFromRole(roleName, groups);
     }
 
@@ -110,7 +106,7 @@ public class TopLevelShell implements ShellDependent, Runnable {
 
     @Command(abbrev = "rm", description = "remove Sentry role(s).")
     public void removeRole(
-            @Param(name = "roleName ...", description = "role names to remove")
+            @Param(name = "roleName", description = "role names to remove")
                     String ...roles) {
         tools.removeRoles(roles);
     }


[07/12] sentry git commit: Moved everything to sentry-tools

Posted by ak...@apache.org.
Moved everything to sentry-tools


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/861ba6f4
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/861ba6f4
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/861ba6f4

Branch: refs/heads/akolb-ha-cli
Commit: 861ba6f4df14159559112cc10162a83f57d1471a
Parents: bc23df3
Author: Alexander Kolbasov <ak...@cloudera.com>
Authored: Mon Dec 12 17:30:03 2016 -0800
Committer: Alexander Kolbasov <ak...@cloudera.com>
Committed: Sun Jan 22 17:09:07 2017 -0800

----------------------------------------------------------------------
 .../provider/db/tools/cli/GroupShell.java       |  65 ------
 .../provider/db/tools/cli/RolesShell.java       |  72 -------
 .../sentry/provider/db/tools/cli/SentryCli.java | 172 ----------------
 .../sentry/provider/db/tools/cli/ShellUtil.java | 205 -------------------
 .../provider/db/tools/cli/TopLevelShell.java    |  93 ---------
 sentry-tools/pom.xml                            |  47 +++++
 .../org/apache/sentry/shell/GroupShell.java     |  65 ++++++
 .../org/apache/sentry/shell/RolesShell.java     |  72 +++++++
 .../java/org/apache/sentry/shell/SentryCli.java | 172 ++++++++++++++++
 .../java/org/apache/sentry/shell/ShellUtil.java | 205 +++++++++++++++++++
 .../org/apache/sentry/shell/TopLevelShell.java  |  93 +++++++++
 11 files changed, 654 insertions(+), 607 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java
deleted file mode 100644
index d4b0bd7..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/GroupShell.java
+++ /dev/null
@@ -1,65 +0,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.
- */
-
-package org.apache.sentry.provider.db.tools.cli;
-
-import com.budhash.cliche.Command;
-import com.budhash.cliche.Shell;
-import com.budhash.cliche.ShellDependent;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-
-import java.util.List;
-
-/**
- * Sentry group manipulation for CLI
- */
-public class GroupShell implements ShellDependent {
-    @Command
-    public List<String> list() {
-        return tools.listGroups();
-    }
-
-    @Command(abbrev = "lr", header = "[groups]",
-            description = "list groups and their roles")
-    public List<String> listRoles() {
-        return tools.listGroupRoles();
-    }
-
-    @Command(description = "Grant role to groups")
-    public void grant(String roleName, String ...groups) {
-        tools.grantGroupsToRole(roleName, groups);
-    }
-
-    @Command(description = "Revoke role from groups")
-    public void revoke(String roleName, String ...groups) {
-        tools.revokeGroupsFromRole(roleName, groups);
-    }
-
-    private final ShellUtil tools;
-    Shell shell;
-
-
-    public GroupShell(SentryPolicyServiceClient sentryClient, String authUser) {
-        this.tools = new ShellUtil(sentryClient, authUser);
-    }
-
-    @Override
-    public void cliSetShell(Shell theShell) {
-        this.shell = theShell;
-    }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java
deleted file mode 100644
index 71f0cab..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/RolesShell.java
+++ /dev/null
@@ -1,72 +0,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.
- */
-
-package org.apache.sentry.provider.db.tools.cli;
-
-import com.budhash.cliche.Command;
-import com.budhash.cliche.Param;
-import com.budhash.cliche.Shell;
-import com.budhash.cliche.ShellDependent;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-
-import java.util.List;
-
-/**
- * Sentry roles manipulation for CLI.
- */
-public class RolesShell implements ShellDependent {
-    @Command(description = "List sentry roles. shows all available roles.")
-    public List<String> list() {
-        return tools.listRoles();
-    }
-
-    @Command(description = "List sentry roles by group")
-    public List<String> list(
-            @Param(name = "groupName", description = "group name for roles")
-            String group) {
-        return tools.listRoles(group);
-    }
-
-    @Command(description = "Create Sentry role(s).")
-    public void create(
-            @Param(name = "roleName", description = "name of role to create")
-            String ...roles) {
-        tools.createRoles(roles);
-    }
-
-    @Command(description = "remove Sentry role(s).")
-    public void remove(
-            @Param(name = "roleName ...", description = "role names to remove")
-            String ...roles) {
-        tools.removeRoles(roles);
-    }
-
-
-    @Override
-    public void cliSetShell(Shell theShell) {
-        this.shell = theShell;
-    }
-
-    private final ShellUtil tools;
-    Shell shell;
-
-    public RolesShell(SentryPolicyServiceClient sentryClient, String authUser) {
-        this.tools = new ShellUtil(sentryClient, authUser);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java
deleted file mode 100644
index f9bbfd3..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/SentryCli.java
+++ /dev/null
@@ -1,172 +0,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.
- */
-
-package org.apache.sentry.provider.db.tools.cli;
-
-import org.apache.commons.cli.*;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.service.thrift.SentryServiceClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
-
-/**
- * Sentry interactive tool
- */
-public class SentryCli {
-    private static final Logger log = LoggerFactory.getLogger(SentryCli.class.getName());
-    private static final String LOG4J_CONF = "log4jConf";
-    private final String[] args;
-    private Options options = new Options();
-    private CommandLine cmd;
-
-    private static final String configOpt = "config";
-    private static final String userOpt = "user";
-
-    private SentryPolicyServiceClient sentryClient;
-
-    public SentryPolicyServiceClient getSentryClient() {
-        return sentryClient;
-    }
-
-    public String getRequestorName() {
-        return requestorName;
-    }
-
-    private String requestorName;
-
-    public static void main(String[] args) {
-        SentryCli cli = new SentryCli(args);
-        // Create interactive shell and run it
-        TopLevelShell shell = new TopLevelShell(cli.getSentryClient(),
-                cli.getRequestorName());
-        shell.run();
-    }
-
-    /**
-     * Construct SentryCli from arguments
-     * @param args command-line arguments
-     */
-    public SentryCli(String[] args) {
-        this.args = args;
-        options.addOption("h", "help", false, "show help");
-        // file path of sentry-site
-        options.addOption("U", userOpt, true, "auth user");
-        options.addOption("c", configOpt, true, "sentry configuration");
-        options.addOption("L", LOG4J_CONF, true, "Location of log4j properties file");
-        CommandLineParser parser = new GnuParser();
-        try {
-            this.cmd = parser.parse(options, args);
-        } catch (ParseException e) {
-            help();
-        }
-        if (cmd.hasOption("h")) {
-            help();
-        }
-        init();
-    }
-
-    /**
-     * Parse command-line arguments.
-     */
-    public void parse() {
-        CommandLineParser parser = new GnuParser();
-        try {
-            cmd = parser.parse(options, args);
-            if (cmd.hasOption("h")) {
-                help();
-            }
-        } catch (ParseException e) {
-            log.warn("error in parsing expression", e);
-            help();
-            System.exit(1);
-        }
-    }
-
-    /**
-     * Initialize CLI
-     */
-    private void init() {
-        Map<String, String> env = System.getenv();
-        String pathConf = cmd.getOptionValue(configOpt);
-        if (pathConf == null) {
-            pathConf = env.get("SENTRY_CONFIG");
-        }
-        if (pathConf == null) {
-            System.out.println("Missing config file");
-            System.exit(1);
-        }
-
-        String log4jconf = cmd.getOptionValue(LOG4J_CONF);
-        if (log4jconf != null && log4jconf.length() > 0) {
-            Properties log4jProperties = new Properties();
-
-            // Firstly load log properties from properties file
-            FileInputStream istream = null;
-            try {
-                istream = new FileInputStream(log4jconf);
-            } catch (FileNotFoundException e) {
-                e.printStackTrace();
-            }
-            try {
-                log4jProperties.load(istream);
-                istream.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-
-            PropertyConfigurator.configure(log4jProperties);
-        }
-        Configuration conf = new Configuration();
-        conf.addResource(new Path(pathConf));
-
-        requestorName = cmd.getOptionValue(userOpt, "");
-        if (requestorName.isEmpty()) {
-            UserGroupInformation ugi = null;
-            try {
-                ugi = UserGroupInformation.getLoginUser();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            requestorName = ugi.getShortUserName();
-        }
-
-        try {
-            sentryClient = SentryServiceClientFactory.create(conf);
-        } catch (Exception e) {
-            System.out.println("Failed to connect to Sentry server: " + e.toString());
-        }
-    }
-
-    private void help() {
-        // This prints out some help
-        HelpFormatter formater = new HelpFormatter();
-        formater.printHelp("sentrycli", options);
-        System.exit(0);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java
deleted file mode 100644
index 3d61405..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/ShellUtil.java
+++ /dev/null
@@ -1,205 +0,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.
- */
-
-package org.apache.sentry.provider.db.tools.cli;
-
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
-import org.apache.sentry.provider.db.service.thrift.TSentryRole;
-
-import java.util.*;
-
-/**
- * ShellUtil implements actual commands
- */
-class ShellUtil {
-
-    List<String> listRoles() {
-        Set<TSentryRole> roles = null;
-        try {
-            roles = sentryClient.listRoles(authUser);
-        } catch (SentryUserException e) {
-            System.out.println("Error listing roles: " + e.toString());
-        }
-        List<String> result = new ArrayList<>();
-        if (roles == null || roles.isEmpty()) {
-            return result;
-        }
-
-        for(TSentryRole role: roles) {
-            result.add(role.getRoleName());
-        }
-
-        Collections.sort(result);
-        return result;
-    }
-
-    List<String> listRoles(String group) {
-        Set<TSentryRole> roles = null;
-        try {
-            roles = sentryClient.listRolesByGroupName(authUser, group);
-        } catch (SentryUserException e) {
-            System.out.println("Error listing roles: " + e.toString());
-        }
-        List<String> result = new ArrayList<>();
-        if (roles == null || roles.isEmpty()) {
-            return result;
-        }
-
-        for(TSentryRole role: roles) {
-            result.add(role.getRoleName());
-        }
-
-        Collections.sort(result);
-        return result;
-    }
-
-    void createRoles(String ...roles) {
-        for (String role: roles) {
-            try {
-                sentryClient.createRole(authUser, role);
-            } catch (SentryUserException e) {
-                System.out.printf("failed to create role %s: %s\n",
-                        role, e.toString());
-            }
-        }
-    }
-
-    void removeRoles(String ...roles) {
-        for (String role: roles) {
-            try {
-                sentryClient.dropRole(authUser, role);
-            } catch (SentryUserException e) {
-                System.out.printf("failed to remove role %s: %s\n",
-                        role, e.toString());
-            }
-        }
-    }
-
-    List<String> listGroups() {
-        Set<TSentryRole> roles = null;
-
-        try {
-            roles = sentryClient.listRoles(authUser);
-        } catch (SentryUserException e) {
-            System.out.println("Error reading roles: " + e.toString());
-        }
-
-        if (roles == null || roles.isEmpty()) {
-            return new ArrayList<>();
-        }
-
-        // Set of all group names
-        Set<String> groupNames = new HashSet<>();
-
-        // Get all group names
-        for (TSentryRole role: roles) {
-            for (TSentryGroup group: role.getGroups()) {
-                groupNames.add(group.getGroupName());
-            }
-        }
-
-        List<String> result = new ArrayList<>(groupNames);
-
-        Collections.sort(result);
-        return result;
-    }
-
-    List<String> listGroupRoles() {
-        Set<TSentryRole> roles = null;
-
-        try {
-            roles = sentryClient.listRoles(authUser);
-        } catch (SentryUserException e) {
-            System.out.println("Error reading roles: " + e.toString());
-        }
-
-        if (roles == null || roles.isEmpty()) {
-            return new ArrayList<>();
-        }
-
-        // Set of all group names
-        Set<String> groupNames = new HashSet<>();
-
-        // Map group to set of roles
-        Map<String, Set<String>> groupInfo = new HashMap<>();
-
-        // Get all group names
-        for (TSentryRole role: roles) {
-            for (TSentryGroup group: role.getGroups()) {
-                String groupName = group.getGroupName();
-                groupNames.add(groupName);
-                Set<String> groupRoles = groupInfo.get(groupName);
-                if (groupRoles != null) {
-                    // Add a new or existing role
-                    groupRoles.add(role.getRoleName());
-                    continue;
-                }
-                // Never seen this group before
-                groupRoles = new HashSet<>();
-                groupRoles.add(role.getRoleName());
-                groupInfo.put(groupName, groupRoles);
-            }
-        }
-
-        List<String> groups = new ArrayList<>(groupNames);
-        Collections.sort(groups);
-
-        // Produce printable result as
-        // group1 = role1, role2, ...
-        // group2 = ...
-        List<String> result = new LinkedList<>();
-        for(String groupName: groups) {
-            result.add(groupName + " = " +
-                    StringUtils.join(groupInfo.get(groupName), ", "));
-        }
-        return result;
-    }
-
-    void grantGroupsToRole(String roleName, String ...groups) {
-        try {
-            sentryClient.grantRoleToGroups(authUser, roleName, Sets.newHashSet(groups));
-        } catch (SentryUserException e) {
-            System.out.printf("Failed to gran role %s to groups: %s\n",
-                    roleName, e.toString());
-        }
-    }
-
-    void revokeGroupsFromRole(String roleName, String ...groups) {
-        try {
-            sentryClient.revokeRoleFromGroups(authUser, roleName, Sets.newHashSet(groups));
-        } catch (SentryUserException e) {
-            System.out.printf("Failed to revoke role %s to groups: %s\n",
-                    roleName, e.toString());
-        }
-    }
-
-
-
-    ShellUtil(SentryPolicyServiceClient sentryClient, String authUser) {
-        this.sentryClient = sentryClient;
-        this.authUser = authUser;
-    }
-
-    private final SentryPolicyServiceClient sentryClient;
-    private final String authUser;
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java
deleted file mode 100644
index 4bc7512..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/cli/TopLevelShell.java
+++ /dev/null
@@ -1,93 +0,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.
- */
-
-package org.apache.sentry.provider.db.tools.cli;
-
-import com.budhash.cliche.*;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Top level commands
- */
-public class TopLevelShell implements ShellDependent, Runnable {
-
-    private final Shell topShell;
-    private final ShellUtil tools;
-    private Shell shell; // top level shell object
-
-    private final String authUser;
-    private final SentryPolicyServiceClient sentryClient;
-
-    TopLevelShell(SentryPolicyServiceClient sentryClient,
-                  String authUser) {
-        this.authUser = authUser;
-        this.sentryClient = sentryClient;
-        this.tools = new ShellUtil(sentryClient, authUser);
-        topShell = ShellFactory.createConsoleShell("sentry",
-                "sentry shell\n" +
-                "Enter ?l to list available commands.",
-                this);
-    }
-
-    @Command(description="listRoles, create and remove roles")
-    public void roles() throws IOException {
-        ShellFactory.createSubshell("roles", shell, "roles commands",
-                new RolesShell(sentryClient, authUser)).commandLoop();
-    }
-
-    @Command(description = "listRoles, create and remove groups")
-    public void groups() throws IOException {
-        ShellFactory.createSubshell("groups", shell, "groups commands",
-                new GroupShell(sentryClient, authUser)).commandLoop();
-    }
-
-    @Command(description = "List sentry roles. shows all available roles.")
-    public List<String> listRoles() {
-        return tools.listRoles();
-    }
-
-    @Command(description = "List sentry roles by group")
-    public List<String> listRoles(
-            @Param(name = "groupName")
-            String group) {
-        return tools.listRoles(group);
-    }
-
-    @Command(abbrev = "lg", header = "[groups]",
-             description = "list groups and their roles")
-    public List<String> listGroups() {
-        return tools.listGroupRoles();
-    }
-
-    @Override
-    public void cliSetShell(Shell theShell) {
-        this.shell = theShell;
-    }
-
-    @Override
-    public void run() {
-        try {
-            this.topShell.commandLoop();
-        } catch (IOException e) {
-            System.out.println("error: " + e.toString());
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-tools/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-tools/pom.xml b/sentry-tools/pom.xml
new file mode 100644
index 0000000..62dd862
--- /dev/null
+++ b/sentry-tools/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+    <parent>
+        <artifactId>sentry</artifactId>
+        <groupId>org.apache.sentry</groupId>
+        <version>1.8.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>sentry-tools</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-cli</groupId>
+            <artifactId>commons-cli</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.budhash.cliche</groupId>
+            <artifactId>cliche-shell</artifactId>
+            <version>0.9.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sentry</groupId>
+            <artifactId>sentry-provider-db</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
+    </build>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
new file mode 100644
index 0000000..3fc7a31
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.sentry.shell;
+
+import com.budhash.cliche.Command;
+import com.budhash.cliche.Shell;
+import com.budhash.cliche.ShellDependent;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.util.List;
+
+/**
+ * Sentry group manipulation for CLI
+ */
+public class GroupShell implements ShellDependent {
+    @Command
+    public List<String> list() {
+        return tools.listGroups();
+    }
+
+    @Command(abbrev = "lr", header = "[groups]",
+            description = "list groups and their roles")
+    public List<String> listRoles() {
+        return tools.listGroupRoles();
+    }
+
+    @Command(description = "Grant role to groups")
+    public void grant(String roleName, String ...groups) {
+        tools.grantGroupsToRole(roleName, groups);
+    }
+
+    @Command(description = "Revoke role from groups")
+    public void revoke(String roleName, String ...groups) {
+        tools.revokeGroupsFromRole(roleName, groups);
+    }
+
+    private final ShellUtil tools;
+    Shell shell;
+
+
+    public GroupShell(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.tools = new ShellUtil(sentryClient, authUser);
+    }
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
new file mode 100644
index 0000000..9ac6637
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
@@ -0,0 +1,72 @@
+/*
+ * 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.sentry.shell;
+
+import com.budhash.cliche.Command;
+import com.budhash.cliche.Param;
+import com.budhash.cliche.Shell;
+import com.budhash.cliche.ShellDependent;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.util.List;
+
+/**
+ * Sentry roles manipulation for CLI.
+ */
+public class RolesShell implements ShellDependent {
+    @Command(description = "List sentry roles. shows all available roles.")
+    public List<String> list() {
+        return tools.listRoles();
+    }
+
+    @Command(description = "List sentry roles by group")
+    public List<String> list(
+            @Param(name = "groupName", description = "group name for roles")
+            String group) {
+        return tools.listRoles(group);
+    }
+
+    @Command(description = "Create Sentry role(s).")
+    public void create(
+            @Param(name = "roleName", description = "name of role to create")
+            String ...roles) {
+        tools.createRoles(roles);
+    }
+
+    @Command(description = "remove Sentry role(s).")
+    public void remove(
+            @Param(name = "roleName ...", description = "role names to remove")
+            String ...roles) {
+        tools.removeRoles(roles);
+    }
+
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+
+    private final ShellUtil tools;
+    Shell shell;
+
+    public RolesShell(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.tools = new ShellUtil(sentryClient, authUser);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
new file mode 100644
index 0000000..61dcc04
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/SentryCli.java
@@ -0,0 +1,172 @@
+/**
+ * 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.sentry.shell;
+
+import org.apache.commons.cli.*;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.service.thrift.SentryServiceClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Sentry interactive tool
+ */
+public class SentryCli {
+    private static final Logger log = LoggerFactory.getLogger(SentryCli.class.getName());
+    private static final String LOG4J_CONF = "log4jConf";
+    private final String[] args;
+    private Options options = new Options();
+    private CommandLine cmd;
+
+    private static final String configOpt = "config";
+    private static final String userOpt = "user";
+
+    private SentryPolicyServiceClient sentryClient;
+
+    public SentryPolicyServiceClient getSentryClient() {
+        return sentryClient;
+    }
+
+    public String getRequestorName() {
+        return requestorName;
+    }
+
+    private String requestorName;
+
+    public static void main(String[] args) {
+        SentryCli cli = new SentryCli(args);
+        // Create interactive shell and run it
+        TopLevelShell shell = new TopLevelShell(cli.getSentryClient(),
+                cli.getRequestorName());
+        shell.run();
+    }
+
+    /**
+     * Construct SentryCli from arguments
+     * @param args command-line arguments
+     */
+    public SentryCli(String[] args) {
+        this.args = args;
+        options.addOption("h", "help", false, "show help");
+        // file path of sentry-site
+        options.addOption("U", userOpt, true, "auth user");
+        options.addOption("c", configOpt, true, "sentry configuration");
+        options.addOption("L", LOG4J_CONF, true, "Location of log4j properties file");
+        CommandLineParser parser = new GnuParser();
+        try {
+            this.cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            help();
+        }
+        if (cmd.hasOption("h")) {
+            help();
+        }
+        init();
+    }
+
+    /**
+     * Parse command-line arguments.
+     */
+    public void parse() {
+        CommandLineParser parser = new GnuParser();
+        try {
+            cmd = parser.parse(options, args);
+            if (cmd.hasOption("h")) {
+                help();
+            }
+        } catch (ParseException e) {
+            log.warn("error in parsing expression", e);
+            help();
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Initialize CLI
+     */
+    private void init() {
+        Map<String, String> env = System.getenv();
+        String pathConf = cmd.getOptionValue(configOpt);
+        if (pathConf == null) {
+            pathConf = env.get("SENTRY_CONFIG");
+        }
+        if (pathConf == null) {
+            System.out.println("Missing config file");
+            System.exit(1);
+        }
+
+        String log4jconf = cmd.getOptionValue(LOG4J_CONF);
+        if (log4jconf != null && log4jconf.length() > 0) {
+            Properties log4jProperties = new Properties();
+
+            // Firstly load log properties from properties file
+            FileInputStream istream = null;
+            try {
+                istream = new FileInputStream(log4jconf);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+            try {
+                log4jProperties.load(istream);
+                istream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            PropertyConfigurator.configure(log4jProperties);
+        }
+        Configuration conf = new Configuration();
+        conf.addResource(new Path(pathConf));
+
+        requestorName = cmd.getOptionValue(userOpt, "");
+        if (requestorName.isEmpty()) {
+            UserGroupInformation ugi = null;
+            try {
+                ugi = UserGroupInformation.getLoginUser();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            requestorName = ugi.getShortUserName();
+        }
+
+        try {
+            sentryClient = SentryServiceClientFactory.create(conf);
+        } catch (Exception e) {
+            System.out.println("Failed to connect to Sentry server: " + e.toString());
+        }
+    }
+
+    private void help() {
+        // This prints out some help
+        HelpFormatter formater = new HelpFormatter();
+        formater.printHelp("sentrycli", options);
+        System.exit(0);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
new file mode 100644
index 0000000..a062c12
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/ShellUtil.java
@@ -0,0 +1,205 @@
+/*
+ * 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.sentry.shell;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+
+import java.util.*;
+
+/**
+ * ShellUtil implements actual commands
+ */
+class ShellUtil {
+
+    List<String> listRoles() {
+        Set<TSentryRole> roles = null;
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error listing roles: " + e.toString());
+        }
+        List<String> result = new ArrayList<>();
+        if (roles == null || roles.isEmpty()) {
+            return result;
+        }
+
+        for(TSentryRole role: roles) {
+            result.add(role.getRoleName());
+        }
+
+        Collections.sort(result);
+        return result;
+    }
+
+    List<String> listRoles(String group) {
+        Set<TSentryRole> roles = null;
+        try {
+            roles = sentryClient.listRolesByGroupName(authUser, group);
+        } catch (SentryUserException e) {
+            System.out.println("Error listing roles: " + e.toString());
+        }
+        List<String> result = new ArrayList<>();
+        if (roles == null || roles.isEmpty()) {
+            return result;
+        }
+
+        for(TSentryRole role: roles) {
+            result.add(role.getRoleName());
+        }
+
+        Collections.sort(result);
+        return result;
+    }
+
+    void createRoles(String ...roles) {
+        for (String role: roles) {
+            try {
+                sentryClient.createRole(authUser, role);
+            } catch (SentryUserException e) {
+                System.out.printf("failed to create role %s: %s\n",
+                        role, e.toString());
+            }
+        }
+    }
+
+    void removeRoles(String ...roles) {
+        for (String role: roles) {
+            try {
+                sentryClient.dropRole(authUser, role);
+            } catch (SentryUserException e) {
+                System.out.printf("failed to remove role %s: %s\n",
+                        role, e.toString());
+            }
+        }
+    }
+
+    List<String> listGroups() {
+        Set<TSentryRole> roles = null;
+
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error reading roles: " + e.toString());
+        }
+
+        if (roles == null || roles.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // Set of all group names
+        Set<String> groupNames = new HashSet<>();
+
+        // Get all group names
+        for (TSentryRole role: roles) {
+            for (TSentryGroup group: role.getGroups()) {
+                groupNames.add(group.getGroupName());
+            }
+        }
+
+        List<String> result = new ArrayList<>(groupNames);
+
+        Collections.sort(result);
+        return result;
+    }
+
+    List<String> listGroupRoles() {
+        Set<TSentryRole> roles = null;
+
+        try {
+            roles = sentryClient.listRoles(authUser);
+        } catch (SentryUserException e) {
+            System.out.println("Error reading roles: " + e.toString());
+        }
+
+        if (roles == null || roles.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // Set of all group names
+        Set<String> groupNames = new HashSet<>();
+
+        // Map group to set of roles
+        Map<String, Set<String>> groupInfo = new HashMap<>();
+
+        // Get all group names
+        for (TSentryRole role: roles) {
+            for (TSentryGroup group: role.getGroups()) {
+                String groupName = group.getGroupName();
+                groupNames.add(groupName);
+                Set<String> groupRoles = groupInfo.get(groupName);
+                if (groupRoles != null) {
+                    // Add a new or existing role
+                    groupRoles.add(role.getRoleName());
+                    continue;
+                }
+                // Never seen this group before
+                groupRoles = new HashSet<>();
+                groupRoles.add(role.getRoleName());
+                groupInfo.put(groupName, groupRoles);
+            }
+        }
+
+        List<String> groups = new ArrayList<>(groupNames);
+        Collections.sort(groups);
+
+        // Produce printable result as
+        // group1 = role1, role2, ...
+        // group2 = ...
+        List<String> result = new LinkedList<>();
+        for(String groupName: groups) {
+            result.add(groupName + " = " +
+                    StringUtils.join(groupInfo.get(groupName), ", "));
+        }
+        return result;
+    }
+
+    void grantGroupsToRole(String roleName, String ...groups) {
+        try {
+            sentryClient.grantRoleToGroups(authUser, roleName, Sets.newHashSet(groups));
+        } catch (SentryUserException e) {
+            System.out.printf("Failed to gran role %s to groups: %s\n",
+                    roleName, e.toString());
+        }
+    }
+
+    void revokeGroupsFromRole(String roleName, String ...groups) {
+        try {
+            sentryClient.revokeRoleFromGroups(authUser, roleName, Sets.newHashSet(groups));
+        } catch (SentryUserException e) {
+            System.out.printf("Failed to revoke role %s to groups: %s\n",
+                    roleName, e.toString());
+        }
+    }
+
+
+
+    ShellUtil(SentryPolicyServiceClient sentryClient, String authUser) {
+        this.sentryClient = sentryClient;
+        this.authUser = authUser;
+    }
+
+    private final SentryPolicyServiceClient sentryClient;
+    private final String authUser;
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/861ba6f4/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
new file mode 100644
index 0000000..c1d8a77
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -0,0 +1,93 @@
+/**
+ * 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.sentry.shell;
+
+import com.budhash.cliche.*;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Top level commands
+ */
+public class TopLevelShell implements ShellDependent, Runnable {
+
+    private final Shell topShell;
+    private final ShellUtil tools;
+    private Shell shell; // top level shell object
+
+    private final String authUser;
+    private final SentryPolicyServiceClient sentryClient;
+
+    TopLevelShell(SentryPolicyServiceClient sentryClient,
+                  String authUser) {
+        this.authUser = authUser;
+        this.sentryClient = sentryClient;
+        this.tools = new ShellUtil(sentryClient, authUser);
+        topShell = ShellFactory.createConsoleShell("sentry",
+                "sentry shell\n" +
+                "Enter ?l to list available commands.",
+                this);
+    }
+
+    @Command(description="listRoles, create and remove roles")
+    public void roles() throws IOException {
+        ShellFactory.createSubshell("roles", shell, "roles commands",
+                new RolesShell(sentryClient, authUser)).commandLoop();
+    }
+
+    @Command(description = "listRoles, create and remove groups")
+    public void groups() throws IOException {
+        ShellFactory.createSubshell("groups", shell, "groups commands",
+                new GroupShell(sentryClient, authUser)).commandLoop();
+    }
+
+    @Command(description = "List sentry roles. shows all available roles.")
+    public List<String> listRoles() {
+        return tools.listRoles();
+    }
+
+    @Command(description = "List sentry roles by group")
+    public List<String> listRoles(
+            @Param(name = "groupName")
+            String group) {
+        return tools.listRoles(group);
+    }
+
+    @Command(abbrev = "lg", header = "[groups]",
+             description = "list groups and their roles")
+    public List<String> listGroups() {
+        return tools.listGroupRoles();
+    }
+
+    @Override
+    public void cliSetShell(Shell theShell) {
+        this.shell = theShell;
+    }
+
+    @Override
+    public void run() {
+        try {
+            this.topShell.commandLoop();
+        } catch (IOException e) {
+            System.out.println("error: " + e.toString());
+        }
+    }
+}