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/b1c1cabd Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/b1c1cabd Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/b1c1cabd Branch: refs/heads/akolb-ha-cli Commit: b1c1cabddda9b255d8fad40cfd2364a480344bff Parents: e5ea89e Author: Alexander Kolbasov <[email protected]> Authored: Mon Dec 12 17:30:03 2016 -0800 Committer: Alexander Kolbasov <[email protected]> Committed: Wed May 10 23:28:29 2017 -0700 ---------------------------------------------------------------------- .../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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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/b1c1cabd/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()); + } + } +}
