HBASE-20199 Add a unit test to verify flush and snapshot permission requirements aren't excessive

Signed-off-by: Ted Yu <yuzhihong@gmail.com>
Signed-off-by: Michael Stack <stack@apache.org>
This commit is contained in:
Josh Elser 2018-03-26 17:52:37 -04:00
parent 09ed7c7a10
commit 69f5d707b6
1 changed files with 96 additions and 2 deletions

View File

@ -19,6 +19,8 @@
package org.apache.hadoop.hbase.security.access;
import static org.apache.hadoop.hbase.AuthUtil.toGroupEntry;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
@ -30,13 +32,22 @@ import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.HashMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessor;
@ -46,10 +57,13 @@ import org.apache.hadoop.hbase.security.AccessDeniedException;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.SecurityTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;
/**
* This class tests operations in MasterRpcServices which require ADMIN access.
@ -74,10 +88,13 @@ import org.junit.experimental.categories.Category;
* But this doesn't work for the tests here, so we go around by doing complete RPCs.
*/
@Category({SecurityTests.class, MediumTests.class})
public class TestAdminOnlyOperations {
public class TestRpcAccessChecks {
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestAdminOnlyOperations.class);
HBaseClassTestRule.forClass(TestRpcAccessChecks.class);
@Rule
public final TestName TEST_NAME = new TestName();
private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
private static Configuration conf;
@ -265,4 +282,81 @@ public class TestAdminOnlyOperations {
verifyAllowed(USER_GROUP_ADMIN, action);
verifiedDeniedServiceException(USER_NON_ADMIN, action);
}
@Test
public void testTableFlush() throws Exception {
TableName tn = TableName.valueOf(TEST_NAME.getMethodName());
TableDescriptor desc = TableDescriptorBuilder.newBuilder(tn)
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("f1")).build();
Action adminAction = (admin) -> {
admin.createTable(desc);
// Avoid giving a global permission which may screw up other tests
SecureTestUtil.grantOnTable(
TEST_UTIL, USER_NON_ADMIN.getShortName(), tn, null, null, Permission.Action.READ,
Permission.Action.WRITE, Permission.Action.CREATE);
};
verifyAllowed(USER_ADMIN, adminAction);
Action userAction = (admin) -> {
Connection conn = admin.getConnection();
final byte[] rowKey = Bytes.toBytes("row1");
final byte[] col = Bytes.toBytes("q1");
final byte[] val = Bytes.toBytes("v1");
try (Table table = conn.getTable(tn)) {
// Write a value
Put p = new Put(rowKey);
p.addColumn(Bytes.toBytes("f1"), col, val);
table.put(p);
// Flush should not require ADMIN permission
admin.flush(tn);
// Nb: ideally, we would verify snapshot permission too (as that was fixed in the
// regression HBASE-20185) but taking a snapshot requires ADMIN permission which
// masks the root issue.
// Make sure we read the value
Result result = table.get(new Get(rowKey));
assertFalse(result.isEmpty());
Cell c = result.getColumnLatestCell(Bytes.toBytes("f1"), col);
assertArrayEquals(val, CellUtil.cloneValue(c));
}
};
verifyAllowed(USER_NON_ADMIN, userAction);
}
@Test
public void testTableFlushAndSnapshot() throws Exception {
TableName tn = TableName.valueOf(TEST_NAME.getMethodName());
TableDescriptor desc = TableDescriptorBuilder.newBuilder(tn)
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("f1")).build();
Action adminAction = (admin) -> {
admin.createTable(desc);
// Giving ADMIN here, but only on this table, *not* globally
SecureTestUtil.grantOnTable(
TEST_UTIL, USER_NON_ADMIN.getShortName(), tn, null, null, Permission.Action.READ,
Permission.Action.WRITE, Permission.Action.CREATE, Permission.Action.ADMIN);
};
verifyAllowed(USER_ADMIN, adminAction);
Action userAction = (admin) -> {
Connection conn = admin.getConnection();
final byte[] rowKey = Bytes.toBytes("row1");
final byte[] col = Bytes.toBytes("q1");
final byte[] val = Bytes.toBytes("v1");
try (Table table = conn.getTable(tn)) {
// Write a value
Put p = new Put(rowKey);
p.addColumn(Bytes.toBytes("f1"), col, val);
table.put(p);
// Flush should not require ADMIN permission
admin.flush(tn);
// Table admin should be sufficient to snapshot this table
admin.snapshot(tn.getNameAsString() + "_snapshot1", tn);
// Read the value just because
Result result = table.get(new Get(rowKey));
assertFalse(result.isEmpty());
Cell c = result.getColumnLatestCell(Bytes.toBytes("f1"), col);
assertArrayEquals(val, CellUtil.cloneValue(c));
}
};
verifyAllowed(USER_NON_ADMIN, userAction);
}
}