Return-Path: X-Original-To: apmail-hbase-commits-archive@www.apache.org Delivered-To: apmail-hbase-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C1B6850A for ; Mon, 20 Aug 2012 21:31:31 +0000 (UTC) Received: (qmail 69962 invoked by uid 500); 20 Aug 2012 21:31:31 -0000 Delivered-To: apmail-hbase-commits-archive@hbase.apache.org Received: (qmail 69930 invoked by uid 500); 20 Aug 2012 21:31:31 -0000 Mailing-List: contact commits-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hbase.apache.org Delivered-To: mailing list commits@hbase.apache.org Received: (qmail 69923 invoked by uid 99); 20 Aug 2012 21:31:31 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 20 Aug 2012 21:31:31 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 20 Aug 2012 21:31:28 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id C17432388A33 for ; Mon, 20 Aug 2012 21:30:43 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1375230 - in /hbase/branches/0.90: CHANGES.txt src/main/java/org/apache/hadoop/hbase/security/User.java src/main/java/org/apache/hadoop/hbase/util/FSUtils.java src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java Date: Mon, 20 Aug 2012 21:30:43 -0000 To: commits@hbase.apache.org From: jmhsieh@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120820213043.C17432388A33@eris.apache.org> Author: jmhsieh Date: Mon Aug 20 21:30:43 2012 New Revision: 1375230 URL: http://svn.apache.org/viewvc?rev=1375230&view=rev Log: HBASE-5714 Add write permissions check before any hbck run that modifies hdfs (Liang Xie) Modified: hbase/branches/0.90/CHANGES.txt hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/security/User.java hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java Modified: hbase/branches/0.90/CHANGES.txt URL: http://svn.apache.org/viewvc/hbase/branches/0.90/CHANGES.txt?rev=1375230&r1=1375229&r2=1375230&view=diff ============================================================================== --- hbase/branches/0.90/CHANGES.txt (original) +++ hbase/branches/0.90/CHANGES.txt Mon Aug 20 21:30:43 2012 @@ -60,6 +60,7 @@ Release 0.90.7 - Unreleased HBASE-6283 [region_mover.rb] Add option to exclude list of hosts on unload instead of just assuming the source node HBASE-6382 Upgrade Jersey to 1.8 to match Hadoop 1 and 2 (David S. Wang) HBASE-6379 [0.90 branch] Backport HBASE-6334 to 0.90 (TestImprovement for TestHRegion.testWritesWhileGetting) (Gregory Chanan) + HBASE-5714 Add write permissions check before any hbck run that modifies hdfs (Liang Xie) NEW FEATURE HBASE-5128 [uber hbck] Online automated repair of table integrity and region consistency problems Modified: hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/security/User.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/security/User.java?rev=1375230&r1=1375229&r2=1375230&view=diff ============================================================================== --- hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/security/User.java (original) +++ hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/security/User.java Mon Aug 20 21:30:43 2012 @@ -63,6 +63,10 @@ public abstract class User { private static Log LOG = LogFactory.getLog(User.class); protected UserGroupInformation ugi; + public UserGroupInformation getUGI() { + return ugi; + } + /** * Returns the full user name. For Kerberos principals this will include * the host and realm portions of the principal name. Modified: hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java?rev=1375230&r1=1375229&r2=1375230&view=diff ============================================================================== --- hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java (original) +++ hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java Mon Aug 20 21:30:43 2012 @@ -28,6 +28,8 @@ import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.PathFilter; +import org.apache.hadoop.fs.permission.FsAction; +import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.RemoteExceptionHandler; @@ -38,6 +40,10 @@ import org.apache.hadoop.hdfs.protocol.A import org.apache.hadoop.hdfs.protocol.FSConstants; import org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException; import org.apache.hadoop.io.SequenceFile; +import org.apache.hadoop.security.AccessControlException; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.util.ReflectionUtils; +import org.apache.hadoop.util.StringUtils; import java.io.DataInputStream; import java.io.EOFException; @@ -649,6 +655,42 @@ public class FSUtils { } /** + * Throw an exception if an action is not permitted by a user on a file. + * + * @param ugi + * the user + * @param file + * the file + * @param action + * the action + */ + public static void checkAccess(UserGroupInformation ugi, FileStatus file, + FsAction action) throws AccessControlException { + if (ugi.getUserName().equals(file.getOwner())) { + if (file.getPermission().getUserAction().implies(action)) { + return; + } + } else if (contains(ugi.getGroupNames(), file.getGroup())) { + if (file.getPermission().getGroupAction().implies(action)) { + return; + } + } else if (file.getPermission().getOtherAction().implies(action)) { + return; + } + throw new AccessControlException("Permission denied:" + " action=" + action + + " path=" + file.getPath() + " user=" + ugi.getUserName()); + } + + private static boolean contains(String[] groups, String user) { + for (String group : groups) { + if (group.equals(user)) { + return true; + } + } + return false; + } + + /** * @param conf * @return True if this filesystem whose scheme is 'hdfs'. * @throws IOException Modified: hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java URL: http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java?rev=1375230&r1=1375229&r2=1375230&view=diff ============================================================================== --- hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java (original) +++ hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java Mon Aug 20 21:30:43 2012 @@ -47,6 +47,8 @@ import org.apache.hadoop.fs.FSDataInputS import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; +import org.apache.hadoop.fs.permission.FsAction; +import org.apache.hadoop.hbase.Abortable; import org.apache.hadoop.hbase.ClusterStatus; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HConstants; @@ -74,11 +76,14 @@ import org.apache.hadoop.hbase.ipc.HRegi import org.apache.hadoop.hbase.master.MasterFileSystem; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.wal.HLog; +import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.util.HBaseFsck.ErrorReporter.ERROR_CODE; import org.apache.hadoop.hbase.util.hbck.TableIntegrityErrorHandler; import org.apache.hadoop.hbase.util.hbck.TableIntegrityErrorHandlerImpl; import org.apache.hadoop.hbase.zookeeper.ZKTable; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; +import org.apache.hadoop.security.AccessControlException; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.zookeeper.KeeperException; import com.google.common.base.Joiner; @@ -176,6 +181,7 @@ public class HBaseFsck { private boolean rerun = false; // if we tried to fix something, rerun hbck private static boolean summary = false; // if we want to print less output private boolean checkMetaOnly = false; + private boolean ignorePreCheckPermission = false; // if pre-check permission /********* * State @@ -1133,6 +1139,27 @@ public class HBaseFsck { } } + private void preCheckPermission() throws IOException, AccessControlException { + if (shouldIgnorePreCheckPermission()) { + return; + } + + Path hbaseDir = new Path(conf.get(HConstants.HBASE_DIR)); + FileSystem fs = hbaseDir.getFileSystem(conf); + UserGroupInformation ugi = User.getCurrent().getUGI(); + FileStatus[] files = fs.listStatus(hbaseDir); + for (FileStatus file : files) { + try { + FSUtils.checkAccess(ugi, file, FsAction.WRITE); + } catch (AccessControlException ace) { + LOG.warn("Got AccessControlException when preCheckPermission ", ace); + System.err.println("Current user " + ugi.getUserName() + " does not have write perms to " + file.getPath() + + ". Please rerun hbck as hdfs user " + file.getOwner()); + throw new AccessControlException(ace); + } + } + } + /** * Deletes region from meta table */ @@ -3049,6 +3076,14 @@ public class HBaseFsck { return fixSplitParents; } + public boolean shouldIgnorePreCheckPermission() { + return ignorePreCheckPermission; + } + + public void setIgnorePreCheckPermission(boolean ignorePreCheckPermission) { + this.ignorePreCheckPermission = ignorePreCheckPermission; + } + /** * @param mm maximum number of regions to merge into a single region. */ @@ -3114,6 +3149,7 @@ public class HBaseFsck { System.err.println(" -sidelineBigOverlaps When fixing region overlaps, allow to sideline big overlaps"); System.err.println(" -maxOverlapsToSideline When fixing region overlaps, allow at most regions to sideline per group. (n=" + DEFAULT_OVERLAPS_TO_SIDELINE +" by default)"); System.err.println(" -fixSplitParents Try to force offline split parents to be online."); + System.err.println(" -ignorePreCheckPermission ignore filesystem permission pre-check"); System.err.println(""); System.err.println(" -repair Shortcut for -fixAssignments -fixMeta -fixHdfsHoles " + "-fixHdfsOrphans -fixHdfsOverlaps -fixVersionFile -sidelineBigOverlaps"); @@ -3193,6 +3229,8 @@ public class HBaseFsck { fsck.setFixTableDesc(true); } else if (cmd.equals("-fixSplitParents")) { fsck.setFixSplitParents(true); + } else if (cmd.equals("-ignorePreCheckPermission")) { + fsck.setIgnorePreCheckPermission(true); } else if (cmd.equals("-repair")) { // this attempts to merge overlapping hdfs regions, needs testing // under load @@ -3249,6 +3287,15 @@ public class HBaseFsck { System.out.println("Allow checking/fixes for table: " + cmd); } } + + // pre-check current user has FS write permission or not + try { + fsck.preCheckPermission(); + } catch (AccessControlException ace) { + Runtime.getRuntime().exit(-1); + } catch (IOException ioe) { + Runtime.getRuntime().exit(-1); + } // do the real work of fsck fsck.connect(); int code = fsck.onlineHbck();