sentry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ak...@apache.org
Subject [05/13] sentry git commit: Initial version of interactive client shell
Date Thu, 11 May 2017 06:45:10 GMT
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/b7903d01
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/b7903d01
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/b7903d01

Branch: refs/heads/akolb-ha-cli
Commit: b7903d01af0922f3468e37b85f5a3f941b7bd18f
Parents: 1151441
Author: Alexander Kolbasov <akolb@cloudera.com>
Authored: Mon Dec 12 12:57:32 2016 -0800
Committer: Alexander Kolbasov <akolb@cloudera.com>
Committed: Wed May 10 23:28:29 2017 -0700

----------------------------------------------------------------------
 .../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/b7903d01/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/b7903d01/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/b7903d01/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/b7903d01/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/b7903d01/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/b7903d01/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());
+        }
+    }
+}


Mime
View raw message