hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From te...@apache.org
Subject svn commit: r1244623 - in /hbase/trunk/security/src: main/java/org/apache/hadoop/hbase/security/access/ test/java/org/apache/hadoop/hbase/security/access/
Date Wed, 15 Feb 2012 18:13:28 GMT
Author: tedyu
Date: Wed Feb 15 18:13:28 2012
New Revision: 1244623

URL: http://svn.apache.org/viewvc?rev=1244623&view=rev
Log:
HBASE-5371 Introduce AccessControllerProtocol.checkPermissions(Permission[] permissons) API
(Enis Soztutar)

Modified:
    hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
    hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java
    hbase/trunk/security/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java

Modified: hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
URL: http://svn.apache.org/viewvc/hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java?rev=1244623&r1=1244622&r2=1244623&view=diff
==============================================================================
--- hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
(original)
+++ hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
Wed Feb 15 18:13:28 2012
@@ -14,17 +14,22 @@
 
 package org.apache.hadoop.hbase.security.access;
 
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.MapMaker;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.HColumnDescriptor;
-import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.client.Delete;
 import org.apache.hadoop.hbase.client.Get;
@@ -52,8 +57,11 @@ import org.apache.hadoop.hbase.security.
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.util.Bytes;
 
-import java.io.IOException;
-import java.util.*;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.MapMaker;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 /**
  * Provides basic authorization checks for data access and administrative
@@ -155,7 +163,7 @@ public class AccessController extends Ba
   /**
    * Version number for AccessControllerProtocol
    */
-  private static final long PROTOCOL_VERSION = 1L;
+  private static final long PROTOCOL_VERSION = 2L;
 
   TableAuthManager authManager = null;
 
@@ -959,6 +967,40 @@ public class AccessController extends Ba
   }
 
   @Override
+  public void checkPermissions(Permission[] permissions) throws IOException {
+    byte[] tableName = regionEnv.getRegion().getTableDesc().getName();
+    for (Permission permission : permissions) {
+      if (permission instanceof TablePermission) {
+        TablePermission tperm = (TablePermission) permission;
+        for (Permission.Action action : permission.getActions()) {
+          if (!Arrays.equals(tperm.getTable(), tableName)) {
+            throw new CoprocessorException(AccessController.class, String.format("This method
"
+                + "can only execute at the table specified in TablePermission. " +
+                "Table of the region:%s , requested table:%s", Bytes.toString(tableName),
+                Bytes.toString(tperm.getTable())));
+          }
+
+          HashMap<byte[], Set<byte[]>> familyMap = Maps.newHashMapWithExpectedSize(1);
+          if (tperm.getFamily() != null) {
+            if (tperm.getQualifier() != null) {
+              familyMap.put(tperm.getFamily(), Sets.newHashSet(tperm.getQualifier()));
+            } else {
+              familyMap.put(tperm.getFamily(), null);
+            }
+          }
+
+          requirePermission(action, regionEnv, familyMap);
+        }
+
+      } else {
+        for (Permission.Action action : permission.getActions()) {
+          requirePermission(action);
+        }
+      }
+    }
+  }
+
+  @Override
   public long getProtocolVersion(String protocol, long clientVersion) throws IOException
{
     return PROTOCOL_VERSION;
   }

Modified: hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java
URL: http://svn.apache.org/viewvc/hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java?rev=1244623&r1=1244622&r2=1244623&view=diff
==============================================================================
--- hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java
(original)
+++ hbase/trunk/security/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java
Wed Feb 15 18:13:28 2012
@@ -18,15 +18,19 @@
 
 package org.apache.hadoop.hbase.security.access;
 
-import org.apache.hadoop.hbase.ipc.CoprocessorProtocol;
-
 import java.io.IOException;
 import java.util.List;
 
+import org.apache.hadoop.hbase.ipc.CoprocessorProtocol;
+
 /**
  * A custom protocol defined for maintaining and querying access control lists.
  */
 public interface AccessControllerProtocol extends CoprocessorProtocol {
+
+  /* V2: Added {@link #checkPermissions(Permission...)}) */
+  public static final long VERSION = 2L;
+
   /**
    * Grants the given user or group the privilege to perform the given actions
    * over the specified scope contained in {@link TablePermission}
@@ -65,4 +69,18 @@ public interface AccessControllerProtoco
    */
   public List<UserPermission> getUserPermissions(byte[] tableName)
       throws IOException;
+
+  /**
+   * Checks whether the given Permissions will pass the access checks for the
+   * current user. Global permissions can be checked from the -acl- table
+   * or any other table, however TablePermissions can only be checked by
+   * the table's regions. If access control checks fail this method throws
+   * AccessDeniedException.
+   * @param permissions to check for. Permission subclasses can be used
+   * to do more specific checks at the table/family/column level.
+   * @throws IOException if there is an error checking the permissions
+   */
+  public void checkPermissions(Permission[] permissions)
+      throws IOException;
+
 }

Modified: hbase/trunk/security/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
URL: http://svn.apache.org/viewvc/hbase/trunk/security/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java?rev=1244623&r1=1244622&r2=1244623&view=diff
==============================================================================
--- hbase/trunk/security/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
(original)
+++ hbase/trunk/security/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
Wed Feb 15 18:13:28 2012
@@ -18,9 +18,14 @@
 
 package org.apache.hadoop.hbase.security.access;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import java.io.IOException;
 import java.security.PrivilegedExceptionAction;
-import java.util.*;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -32,7 +37,17 @@ import org.apache.hadoop.hbase.HRegionIn
 import org.apache.hadoop.hbase.HServerAddress;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.ServerName;
-import org.apache.hadoop.hbase.client.*;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Increment;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.coprocessor.CoprocessorException;
 import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
@@ -43,8 +58,6 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
-
 /**
  * Performs authorization checks for common operations, according to different
  * levels of authorized users.
@@ -126,6 +139,13 @@ public class TestAccessController {
     }
   }
 
+  public void verifyAllowed(PrivilegedExceptionAction action, User... users)
+    throws Exception {
+    for (User user : users) {
+      verifyAllowed(user, action);
+    }
+  }
+
   public void verifyDenied(User user, PrivilegedExceptionAction action)
     throws Exception {
     try {
@@ -151,6 +171,13 @@ public class TestAccessController {
     }
   }
 
+  public void verifyDenied(PrivilegedExceptionAction action, User... users)
+      throws Exception {
+      for (User user : users) {
+        verifyDenied(user, action);
+      }
+    }
+
   @Test
   public void testTableCreate() throws Exception {
     PrivilegedExceptionAction createTable = new PrivilegedExceptionAction() {
@@ -977,4 +1004,193 @@ public class TestAccessController {
     admin.disableTable(tableName);
     admin.deleteTable(tableName);
   }
+
+  /** global operations*/
+  private void verifyGlobal(PrivilegedExceptionAction<?> action) throws Exception {
+    // should be allowed
+    verifyAllowed(SUPERUSER, action);
+
+    // should be denied
+    verifyDenied(USER_OWNER, action);
+    verifyDenied(USER_RW, action);
+    verifyDenied(USER_NONE, action);
+    verifyDenied(USER_RO, action);
+  }
+
+  public void checkGlobalPerms(Permission.Action... actions) throws IOException {
+    HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
+    AccessControllerProtocol protocol =
+        acl.coprocessorProxy(AccessControllerProtocol.class, new byte[0]);
+
+    Permission[] perms = new Permission[actions.length];
+    for (int i=0; i < actions.length; i++) {
+      perms[i] = new Permission(actions[i]);
+    }
+
+    protocol.checkPermissions(perms);
+  }
+
+  public void checkTablePerms(byte[] table, byte[] family, byte[] column,
+      Permission.Action... actions) throws IOException {
+    Permission[] perms = new Permission[actions.length];
+    for (int i=0; i < actions.length; i++) {
+      perms[i] = new TablePermission(table, family, column, actions[i]);
+    }
+
+    checkTablePerms(table, perms);
+  }
+
+  public void checkTablePerms(byte[] table, Permission...perms) throws IOException {
+    HTable acl = new HTable(conf, table);
+    AccessControllerProtocol protocol =
+        acl.coprocessorProxy(AccessControllerProtocol.class, new byte[0]);
+
+    protocol.checkPermissions(perms);
+  }
+
+  public void grant(AccessControllerProtocol protocol, User user, byte[] t, byte[] f,
+      byte[] q, Permission.Action... actions) throws IOException {
+    protocol.grant(Bytes.toBytes(user.getShortName()), new TablePermission(t, f, q, actions));
+  }
+
+  @Test
+  public void testCheckPermissions() throws Exception {
+    final HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
+    final AccessControllerProtocol protocol =
+        acl.coprocessorProxy(AccessControllerProtocol.class, TEST_TABLE);
+
+    //--------------------------------------
+    //test global permissions
+    PrivilegedExceptionAction<Void> globalAdmin = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkGlobalPerms(Permission.Action.ADMIN);
+        return null;
+      }
+    };
+    //verify that only superuser can admin
+    verifyGlobal(globalAdmin);
+
+    //--------------------------------------
+    //test multiple permissions
+    PrivilegedExceptionAction<Void> globalReadWrite = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkGlobalPerms(Permission.Action.READ, Permission.Action.WRITE);
+        return null;
+      }
+    };
+
+    verifyGlobal(globalReadWrite);
+
+    //--------------------------------------
+    //table/column/qualifier level permissions
+    final byte[] TEST_Q1 = Bytes.toBytes("q1");
+    final byte[] TEST_Q2 = Bytes.toBytes("q2");
+
+    User userTable = User.createUserForTesting(conf, "user_check_perms_table", new String[0]);
+    User userColumn = User.createUserForTesting(conf, "user_check_perms_family", new String[0]);
+    User userQualifier = User.createUserForTesting(conf, "user_check_perms_q", new String[0]);
+
+    grant(protocol, userTable, TEST_TABLE, null, null, Permission.Action.READ);
+    grant(protocol, userColumn, TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ);
+    grant(protocol, userQualifier, TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ);
+
+    PrivilegedExceptionAction<Void> tableRead = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkTablePerms(TEST_TABLE, null, null, Permission.Action.READ);
+        return null;
+      }
+    };
+
+    PrivilegedExceptionAction<Void> columnRead = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkTablePerms(TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ);
+        return null;
+      }
+    };
+
+    PrivilegedExceptionAction<Void> qualifierRead = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkTablePerms(TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ);
+        return null;
+      }
+    };
+
+    PrivilegedExceptionAction<Void> multiQualifierRead = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkTablePerms(TEST_TABLE, new Permission[] {
+          new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ),
+          new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q2, Permission.Action.READ),
+        });
+        return null;
+      }
+    };
+
+    PrivilegedExceptionAction<Void> globalAndTableRead = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkTablePerms(TEST_TABLE, new Permission[] {
+          new Permission(Permission.Action.READ),
+          new TablePermission(TEST_TABLE, null, (byte[])null, Permission.Action.READ),
+        });
+        return null;
+      }
+    };
+
+    PrivilegedExceptionAction<Void> noCheck = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkTablePerms(TEST_TABLE, new Permission[0]);
+        return null;
+      }
+    };
+
+    verifyAllowed(tableRead, SUPERUSER, userTable);
+    verifyDenied(tableRead, userColumn, userQualifier);
+
+    verifyAllowed(columnRead, SUPERUSER, userTable, userColumn);
+    verifyDenied(columnRead, userQualifier);
+
+    verifyAllowed(qualifierRead, SUPERUSER, userTable, userColumn, userQualifier);
+
+    verifyAllowed(multiQualifierRead, SUPERUSER, userTable, userColumn);
+    verifyDenied(multiQualifierRead, userQualifier);
+
+    verifyAllowed(globalAndTableRead, SUPERUSER);
+    verifyDenied(globalAndTableRead, userTable, userColumn, userQualifier);
+
+    verifyAllowed(noCheck, SUPERUSER, userTable, userColumn, userQualifier);
+
+    //--------------------------------------
+    //test family level multiple permissions
+    PrivilegedExceptionAction<Void> familyReadWrite = new PrivilegedExceptionAction<Void>()
{
+      @Override
+      public Void run() throws Exception {
+        checkTablePerms(TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ,
+            Permission.Action.WRITE);
+        return null;
+      }
+    };
+    // should be allowed
+    verifyAllowed(familyReadWrite, SUPERUSER, USER_OWNER, USER_RW);
+    // should be denied
+    verifyDenied(familyReadWrite, USER_NONE, USER_RO);
+
+    //--------------------------------------
+    //check for wrong table region
+    try {
+      //but ask for TablePermissions for TEST_TABLE
+      protocol.checkPermissions(new Permission[] {(Permission) new TablePermission(
+          TEST_TABLE, null, (byte[])null, Permission.Action.CREATE)});
+      fail("this should have thrown CoprocessorException");
+    } catch(CoprocessorException ex) {
+      //expected
+    }
+
+  }
 }



Mime
View raw message