1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.access;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25
26 import java.io.IOException;
27 import java.lang.reflect.UndeclaredThrowableException;
28 import java.security.PrivilegedActionException;
29 import java.security.PrivilegedExceptionAction;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.NavigableMap;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.conf.Configuration;
37 import org.apache.hadoop.fs.FileStatus;
38 import org.apache.hadoop.fs.FileSystem;
39 import org.apache.hadoop.fs.Path;
40 import org.apache.hadoop.fs.permission.FsPermission;
41 import org.apache.hadoop.hbase.Coprocessor;
42 import org.apache.hadoop.hbase.HBaseTestingUtility;
43 import org.apache.hadoop.hbase.HColumnDescriptor;
44 import org.apache.hadoop.hbase.HConstants;
45 import org.apache.hadoop.hbase.HRegionInfo;
46 import org.apache.hadoop.hbase.HTableDescriptor;
47 import org.apache.hadoop.hbase.KeyValue;
48 import org.apache.hadoop.hbase.LargeTests;
49 import org.apache.hadoop.hbase.MiniHBaseCluster;
50 import org.apache.hadoop.hbase.ServerName;
51 import org.apache.hadoop.hbase.TableName;
52 import org.apache.hadoop.hbase.TableNotFoundException;
53 import org.apache.hadoop.hbase.client.Append;
54 import org.apache.hadoop.hbase.client.Delete;
55 import org.apache.hadoop.hbase.client.Get;
56 import org.apache.hadoop.hbase.client.HBaseAdmin;
57 import org.apache.hadoop.hbase.client.HTable;
58 import org.apache.hadoop.hbase.client.Increment;
59 import org.apache.hadoop.hbase.client.Put;
60 import org.apache.hadoop.hbase.client.Result;
61 import org.apache.hadoop.hbase.client.ResultScanner;
62 import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
63 import org.apache.hadoop.hbase.client.Scan;
64 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
65 import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
66 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
67 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
68 import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
69 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
70 import org.apache.hadoop.hbase.io.hfile.HFile;
71 import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
72 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
73 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
74 import org.apache.hadoop.hbase.protobuf.RequestConverter;
75 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
76 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
77 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
78 import org.apache.hadoop.hbase.regionserver.HRegion;
79 import org.apache.hadoop.hbase.regionserver.HRegionServer;
80 import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
81 import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
82 import org.apache.hadoop.hbase.regionserver.ScanType;
83 import org.apache.hadoop.hbase.security.AccessDeniedException;
84 import org.apache.hadoop.hbase.security.User;
85 import org.apache.hadoop.hbase.security.access.Permission.Action;
86 import org.apache.hadoop.hbase.util.Bytes;
87 import org.apache.hadoop.hbase.util.JVMClusterUtil;
88 import org.apache.hadoop.hbase.util.TestTableName;
89 import org.junit.After;
90 import org.junit.AfterClass;
91 import org.junit.Before;
92 import org.junit.BeforeClass;
93 import org.junit.Rule;
94 import org.junit.Test;
95 import org.junit.experimental.categories.Category;
96
97 import com.google.protobuf.BlockingRpcChannel;
98 import com.google.protobuf.ServiceException;
99
100
101
102
103
104 @Category(LargeTests.class)
105 @SuppressWarnings("rawtypes")
106 public class TestAccessController extends SecureTestUtil {
107 private static final Log LOG = LogFactory.getLog(TestAccessController.class);
108 @Rule public TestTableName TEST_TABLE = new TestTableName();
109 private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
110 private static Configuration conf;
111
112
113 private static User SUPERUSER;
114
115 private static User USER_ADMIN;
116
117 private static User USER_RW;
118
119 private static User USER_RO;
120
121 private static User USER_OWNER;
122
123 private static User USER_CREATE;
124
125 private static User USER_NONE;
126
127 private static TableName TEST_TABLE2 =
128 TableName.valueOf("testtable2");
129 private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
130
131 private static MasterCoprocessorEnvironment CP_ENV;
132 private static AccessController ACCESS_CONTROLLER;
133 private static RegionServerCoprocessorEnvironment RSCP_ENV;
134 private RegionCoprocessorEnvironment RCP_ENV;
135
136 static void verifyConfiguration(Configuration conf) {
137 if (!(conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY)
138 .contains(AccessController.class.getName())
139 && conf.get(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY)
140 .contains(AccessController.class.getName())
141 && conf.get(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY)
142 .contains(AccessController.class.getName()))) {
143 throw new RuntimeException("AccessController is missing from a system coprocessor list");
144 }
145 }
146
147 @BeforeClass
148 public static void setupBeforeClass() throws Exception {
149
150 conf = TEST_UTIL.getConfiguration();
151 conf.set("hbase.master.hfilecleaner.plugins",
152 "org.apache.hadoop.hbase.master.cleaner.HFileLinkCleaner," +
153 "org.apache.hadoop.hbase.master.snapshot.SnapshotHFileCleaner");
154 conf.set("hbase.master.logcleaner.plugins",
155 "org.apache.hadoop.hbase.master.snapshot.SnapshotLogCleaner");
156 SecureTestUtil.enableSecurity(conf);
157
158 verifyConfiguration(conf);
159
160 TEST_UTIL.startMiniCluster();
161 MasterCoprocessorHost cpHost = TEST_UTIL.getMiniHBaseCluster().getMaster().getCoprocessorHost();
162 cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
163 ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(AccessController.class.getName());
164 CP_ENV = cpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
165 Coprocessor.PRIORITY_HIGHEST, 1, conf);
166 RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
167 .getCoprocessorHost();
168 RSCP_ENV = rsHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
169 Coprocessor.PRIORITY_HIGHEST, 1, conf);
170
171
172 TEST_UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME.getName());
173
174
175 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
176 USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]);
177 USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
178 USER_RO = User.createUserForTesting(conf, "rouser", new String[0]);
179 USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
180 USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]);
181 USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]);
182 }
183
184 @AfterClass
185 public static void tearDownAfterClass() throws Exception {
186 TEST_UTIL.shutdownMiniCluster();
187 }
188
189 @Before
190 public void setUp() throws Exception {
191
192 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
193 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
194 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
195 htd.setOwner(USER_OWNER);
196 admin.createTable(htd);
197 TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName().getName());
198
199 HRegion region = TEST_UTIL.getHBaseCluster().getRegions(TEST_TABLE.getTableName()).get(0);
200 RegionCoprocessorHost rcpHost = region.getCoprocessorHost();
201 RCP_ENV = rcpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
202 Coprocessor.PRIORITY_HIGHEST, 1, conf);
203
204
205 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
206 try {
207 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
208 AccessControlService.BlockingInterface protocol =
209 AccessControlService.newBlockingStub(service);
210
211 protocol.grant(null, RequestConverter.buildGrantRequest(USER_ADMIN.getShortName(),
212 AccessControlProtos.Permission.Action.ADMIN,
213 AccessControlProtos.Permission.Action.CREATE,
214 AccessControlProtos.Permission.Action.READ,
215 AccessControlProtos.Permission.Action.WRITE));
216
217 protocol.grant(null, RequestConverter.buildGrantRequest(USER_RW.getShortName(),
218 TEST_TABLE.getTableName(), TEST_FAMILY, null,
219 AccessControlProtos.Permission.Action.READ,
220 AccessControlProtos.Permission.Action.WRITE));
221
222
223 protocol.grant(null, RequestConverter.buildGrantRequest(USER_CREATE.getShortName(),
224 TEST_TABLE.getTableName(), null, null,
225 AccessControlProtos.Permission.Action.CREATE,
226 AccessControlProtos.Permission.Action.READ,
227 AccessControlProtos.Permission.Action.WRITE));
228
229 protocol.grant(null, RequestConverter.buildGrantRequest(USER_RO.getShortName(), TEST_TABLE.getTableName(),
230 TEST_FAMILY, null, AccessControlProtos.Permission.Action.READ));
231
232 assertEquals(4, AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName()).size());
233 } finally {
234 acl.close();
235 }
236 }
237
238 @After
239 public void tearDown() throws Exception {
240
241 try {
242 TEST_UTIL.deleteTable(TEST_TABLE.getTableName());
243 } catch (TableNotFoundException ex) {
244
245 LOG.info("Test deleted table " + TEST_TABLE.getTableName());
246 }
247 assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName()).size());
248 }
249
250 @Override
251 public void verifyAllowed(PrivilegedExceptionAction action, User... users) throws Exception {
252 for (User user : users) {
253 verifyAllowed(user, action);
254 }
255 }
256
257 @Override
258 public void verifyDenied(User user, PrivilegedExceptionAction... actions) throws Exception {
259 for (PrivilegedExceptionAction action : actions) {
260 try {
261 user.runAs(action);
262 fail("Expected AccessDeniedException for user '" + user.getShortName() + "'");
263 } catch (IOException e) {
264 boolean isAccessDeniedException = false;
265 if(e instanceof RetriesExhaustedWithDetailsException) {
266
267
268
269 for(Throwable ex : ((RetriesExhaustedWithDetailsException) e).getCauses()) {
270 if (ex instanceof AccessDeniedException) {
271 isAccessDeniedException = true;
272 break;
273 }
274 }
275 }
276 else {
277
278
279 Throwable ex = e;
280 do {
281 if (ex instanceof AccessDeniedException) {
282 isAccessDeniedException = true;
283 break;
284 }
285 } while((ex = ex.getCause()) != null);
286 }
287 if (!isAccessDeniedException) {
288 fail("Not receiving AccessDeniedException for user '" + user.getShortName() + "'");
289 }
290 } catch (UndeclaredThrowableException ute) {
291
292 Throwable ex = ute.getUndeclaredThrowable();
293 if (ex instanceof PrivilegedActionException) {
294 ex = ((PrivilegedActionException) ex).getException();
295 }
296 if (ex instanceof ServiceException) {
297 ServiceException se = (ServiceException)ex;
298 if (se.getCause() != null && se.getCause() instanceof AccessDeniedException) {
299
300 return;
301 }
302 }
303 fail("Not receiving AccessDeniedException for user '" + user.getShortName() + "'");
304 }
305 }
306 }
307
308 @Override
309 public void verifyDenied(PrivilegedExceptionAction action, User... users) throws Exception {
310 for (User user : users) {
311 verifyDenied(user, action);
312 }
313 }
314
315 @Test
316 public void testTableCreate() throws Exception {
317 PrivilegedExceptionAction createTable = new PrivilegedExceptionAction() {
318 @Override
319 public Object run() throws Exception {
320 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("testnewtable"));
321 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
322 ACCESS_CONTROLLER.preCreateTable(ObserverContext.createAndPrepare(CP_ENV, null), htd, null);
323 return null;
324 }
325 };
326
327
328 verifyAllowed(createTable, SUPERUSER, USER_ADMIN);
329
330
331 verifyDenied(createTable, USER_CREATE, USER_RW, USER_RO, USER_NONE);
332 }
333
334 @Test
335 public void testTableModify() throws Exception {
336 PrivilegedExceptionAction modifyTable = new PrivilegedExceptionAction() {
337 @Override
338 public Object run() throws Exception {
339 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
340 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
341 htd.addFamily(new HColumnDescriptor("fam_" + User.getCurrent().getShortName()));
342 ACCESS_CONTROLLER.preModifyTable(ObserverContext.createAndPrepare(CP_ENV, null),
343 TEST_TABLE.getTableName(), htd);
344 return null;
345 }
346 };
347
348 verifyAllowed(modifyTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER);
349 verifyDenied(modifyTable, USER_RW, USER_RO, USER_NONE);
350 }
351
352 @Test
353 public void testTableDelete() throws Exception {
354 PrivilegedExceptionAction deleteTable = new PrivilegedExceptionAction() {
355 @Override
356 public Object run() throws Exception {
357 ACCESS_CONTROLLER
358 .preDeleteTable(ObserverContext.createAndPrepare(CP_ENV, null), TEST_TABLE.getTableName());
359 return null;
360 }
361 };
362
363 verifyAllowed(deleteTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER);
364 verifyDenied(deleteTable, USER_RW, USER_RO, USER_NONE);
365 }
366
367 @Test
368 public void testAddColumn() throws Exception {
369 final HColumnDescriptor hcd = new HColumnDescriptor("fam_new");
370 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
371 @Override
372 public Object run() throws Exception {
373 ACCESS_CONTROLLER.preAddColumn(ObserverContext.createAndPrepare(CP_ENV, null), TEST_TABLE.getTableName(),
374 hcd);
375 return null;
376 }
377 };
378
379 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER);
380 verifyDenied(action, USER_RW, USER_RO, USER_NONE);
381 }
382
383 @Test
384 public void testModifyColumn() throws Exception {
385 final HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
386 hcd.setMaxVersions(10);
387 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
388 @Override
389 public Object run() throws Exception {
390 ACCESS_CONTROLLER.preModifyColumn(ObserverContext.createAndPrepare(CP_ENV, null),
391 TEST_TABLE.getTableName(), hcd);
392 return null;
393 }
394 };
395
396 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER);
397 verifyDenied(action, USER_RW, USER_RO, USER_NONE);
398 }
399
400 @Test
401 public void testDeleteColumn() throws Exception {
402 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
403 @Override
404 public Object run() throws Exception {
405 ACCESS_CONTROLLER.preDeleteColumn(ObserverContext.createAndPrepare(CP_ENV, null),
406 TEST_TABLE.getTableName(), TEST_FAMILY);
407 return null;
408 }
409 };
410
411 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER);
412 verifyDenied(action, USER_RW, USER_RO, USER_NONE);
413 }
414
415 @Test
416 public void testTableDisable() throws Exception {
417 PrivilegedExceptionAction disableTable = new PrivilegedExceptionAction() {
418 @Override
419 public Object run() throws Exception {
420 ACCESS_CONTROLLER.preDisableTable(ObserverContext.createAndPrepare(CP_ENV, null),
421 TEST_TABLE.getTableName());
422 return null;
423 }
424 };
425
426 PrivilegedExceptionAction disableAclTable = new PrivilegedExceptionAction() {
427 @Override
428 public Object run() throws Exception {
429 ACCESS_CONTROLLER.preDisableTable(ObserverContext.createAndPrepare(CP_ENV, null),
430 AccessControlLists.ACL_TABLE_NAME);
431 return null;
432 }
433 };
434
435 verifyAllowed(disableTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER);
436 verifyDenied(disableTable, USER_RW, USER_RO, USER_NONE);
437
438
439 verifyDenied(disableAclTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_RW, USER_RO);
440 }
441
442 @Test
443 public void testTableEnable() throws Exception {
444 PrivilegedExceptionAction enableTable = new PrivilegedExceptionAction() {
445 @Override
446 public Object run() throws Exception {
447 ACCESS_CONTROLLER
448 .preEnableTable(ObserverContext.createAndPrepare(CP_ENV, null), TEST_TABLE.getTableName());
449 return null;
450 }
451 };
452
453 verifyAllowed(enableTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER);
454 verifyDenied(enableTable, USER_RW, USER_RO, USER_NONE);
455 }
456
457 @Test
458 public void testMove() throws Exception {
459 Map<HRegionInfo, ServerName> regions;
460 HTable table = new HTable(TEST_UTIL.getConfiguration(), TEST_TABLE.getTableName());
461 try {
462 regions = table.getRegionLocations();
463 } finally {
464 table.close();
465 }
466 final Map.Entry<HRegionInfo, ServerName> firstRegion = regions.entrySet().iterator().next();
467 final ServerName server = TEST_UTIL.getHBaseCluster().getRegionServer(0).getServerName();
468 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
469 @Override
470 public Object run() throws Exception {
471 ACCESS_CONTROLLER.preMove(ObserverContext.createAndPrepare(CP_ENV, null),
472 firstRegion.getKey(), server, server);
473 return null;
474 }
475 };
476
477 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
478 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
479 }
480
481 @Test
482 public void testAssign() throws Exception {
483 Map<HRegionInfo, ServerName> regions;
484 HTable table = new HTable(TEST_UTIL.getConfiguration(), TEST_TABLE.getTableName());
485 try {
486 regions = table.getRegionLocations();
487 } finally {
488 table.close();
489 }
490 final Map.Entry<HRegionInfo, ServerName> firstRegion = regions.entrySet().iterator().next();
491
492 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
493 @Override
494 public Object run() throws Exception {
495 ACCESS_CONTROLLER.preAssign(ObserverContext.createAndPrepare(CP_ENV, null),
496 firstRegion.getKey());
497 return null;
498 }
499 };
500
501 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
502 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
503 }
504
505 @Test
506 public void testUnassign() throws Exception {
507 Map<HRegionInfo, ServerName> regions;
508 HTable table = new HTable(TEST_UTIL.getConfiguration(), TEST_TABLE.getTableName());
509 try {
510 regions = table.getRegionLocations();
511 } finally {
512 table.close();
513 }
514 final Map.Entry<HRegionInfo, ServerName> firstRegion = regions.entrySet().iterator().next();
515
516 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
517 @Override
518 public Object run() throws Exception {
519 ACCESS_CONTROLLER.preUnassign(ObserverContext.createAndPrepare(CP_ENV, null),
520 firstRegion.getKey(), false);
521 return null;
522 }
523 };
524
525 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
526 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
527 }
528
529 @Test
530 public void testRegionOffline() throws Exception {
531 Map<HRegionInfo, ServerName> regions;
532 HTable table = new HTable(TEST_UTIL.getConfiguration(), TEST_TABLE.getTableName());
533 try {
534 regions = table.getRegionLocations();
535 } finally {
536 table.close();
537 }
538 final Map.Entry<HRegionInfo, ServerName> firstRegion = regions.entrySet().iterator().next();
539
540 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
541 @Override
542 public Object run() throws Exception {
543 ACCESS_CONTROLLER.preRegionOffline(ObserverContext.createAndPrepare(CP_ENV, null),
544 firstRegion.getKey());
545 return null;
546 }
547 };
548
549 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
550 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
551 }
552
553 @Test
554 public void testBalance() throws Exception {
555 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
556 @Override
557 public Object run() throws Exception {
558 ACCESS_CONTROLLER.preBalance(ObserverContext.createAndPrepare(CP_ENV, null));
559 return null;
560 }
561 };
562
563 verifyAllowed(action, SUPERUSER, USER_ADMIN);
564 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
565 }
566
567 @Test
568 public void testBalanceSwitch() throws Exception {
569 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
570 @Override
571 public Object run() throws Exception {
572 ACCESS_CONTROLLER.preBalanceSwitch(ObserverContext.createAndPrepare(CP_ENV, null), true);
573 return null;
574 }
575 };
576
577 verifyAllowed(action, SUPERUSER, USER_ADMIN);
578 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
579 }
580
581 @Test
582 public void testShutdown() throws Exception {
583 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
584 @Override
585 public Object run() throws Exception {
586 ACCESS_CONTROLLER.preShutdown(ObserverContext.createAndPrepare(CP_ENV, null));
587 return null;
588 }
589 };
590
591 verifyAllowed(action, SUPERUSER, USER_ADMIN);
592 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
593 }
594
595 @Test
596 public void testStopMaster() throws Exception {
597 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
598 @Override
599 public Object run() throws Exception {
600 ACCESS_CONTROLLER.preStopMaster(ObserverContext.createAndPrepare(CP_ENV, null));
601 return null;
602 }
603 };
604
605 verifyAllowed(action, SUPERUSER, USER_ADMIN);
606 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
607 }
608
609 private void verifyWrite(PrivilegedExceptionAction action) throws Exception {
610 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW);
611 verifyDenied(action, USER_NONE, USER_RO);
612 }
613
614 @Test
615 public void testSplit() throws Exception {
616 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
617 @Override
618 public Object run() throws Exception {
619 ACCESS_CONTROLLER.preSplit(ObserverContext.createAndPrepare(RCP_ENV, null));
620 return null;
621 }
622 };
623
624 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
625 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
626 }
627
628 @Test
629 public void testSplitWithSplitRow() throws Exception {
630 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
631 @Override
632 public Object run() throws Exception {
633 ACCESS_CONTROLLER.preSplit(
634 ObserverContext.createAndPrepare(RCP_ENV, null),
635 Bytes.toBytes("row2"));
636 return null;
637 }
638 };
639
640 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
641 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
642 }
643
644
645 @Test
646 public void testFlush() throws Exception {
647 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
648 @Override
649 public Object run() throws Exception {
650 ACCESS_CONTROLLER.preFlush(ObserverContext.createAndPrepare(RCP_ENV, null));
651 return null;
652 }
653 };
654
655 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
656 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
657 }
658
659 @Test
660 public void testCompact() throws Exception {
661 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
662 @Override
663 public Object run() throws Exception {
664 ACCESS_CONTROLLER.preCompact(ObserverContext.createAndPrepare(RCP_ENV, null), null, null,
665 ScanType.COMPACT_RETAIN_DELETES);
666 return null;
667 }
668 };
669
670 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
671 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
672 }
673
674 @Test
675 public void testPreCompactSelection() throws Exception {
676 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
677 @Override
678 public Object run() throws Exception {
679 ACCESS_CONTROLLER.preCompactSelection(ObserverContext.createAndPrepare(RCP_ENV, null), null, null);
680 return null;
681 }
682 };
683
684 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
685 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
686 }
687
688 private void verifyRead(PrivilegedExceptionAction action) throws Exception {
689 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO);
690 verifyDenied(action, USER_NONE);
691 }
692
693 private void verifyReadWrite(PrivilegedExceptionAction action) throws Exception {
694 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW);
695 verifyDenied(action, USER_NONE, USER_RO);
696 }
697
698 @Test
699 public void testRead() throws Exception {
700
701 PrivilegedExceptionAction getAction = new PrivilegedExceptionAction() {
702 @Override
703 public Object run() throws Exception {
704 Get g = new Get(Bytes.toBytes("random_row"));
705 g.addFamily(TEST_FAMILY);
706 HTable t = new HTable(conf, TEST_TABLE.getTableName());
707 try {
708 t.get(g);
709 } finally {
710 t.close();
711 }
712 return null;
713 }
714 };
715 verifyRead(getAction);
716
717
718 PrivilegedExceptionAction scanAction = new PrivilegedExceptionAction() {
719 @Override
720 public Object run() throws Exception {
721 Scan s = new Scan();
722 s.addFamily(TEST_FAMILY);
723
724 HTable table = new HTable(conf, TEST_TABLE.getTableName());
725 try {
726 ResultScanner scanner = table.getScanner(s);
727 try {
728 for (Result r = scanner.next(); r != null; r = scanner.next()) {
729
730 }
731 } catch (IOException e) {
732 } finally {
733 scanner.close();
734 }
735 } finally {
736 table.close();
737 }
738 return null;
739 }
740 };
741 verifyRead(scanAction);
742 }
743
744 @Test
745
746 public void testWrite() throws Exception {
747
748 PrivilegedExceptionAction putAction = new PrivilegedExceptionAction() {
749 @Override
750 public Object run() throws Exception {
751 Put p = new Put(Bytes.toBytes("random_row"));
752 p.add(TEST_FAMILY, Bytes.toBytes("Qualifier"), Bytes.toBytes(1));
753 HTable t = new HTable(conf, TEST_TABLE.getTableName());
754 try {
755 t.put(p);
756 } finally {
757 t.close();
758 }
759 return null;
760 }
761 };
762 verifyWrite(putAction);
763
764
765 PrivilegedExceptionAction deleteAction = new PrivilegedExceptionAction() {
766 @Override
767 public Object run() throws Exception {
768 Delete d = new Delete(Bytes.toBytes("random_row"));
769 d.deleteFamily(TEST_FAMILY);
770 HTable t = new HTable(conf, TEST_TABLE.getTableName());
771 try {
772 t.delete(d);
773 } finally {
774 t.close();
775 }
776 return null;
777 }
778 };
779 verifyWrite(deleteAction);
780
781
782 PrivilegedExceptionAction incrementAction = new PrivilegedExceptionAction() {
783 @Override
784 public Object run() throws Exception {
785 Increment inc = new Increment(Bytes.toBytes("random_row"));
786 inc.addColumn(TEST_FAMILY, Bytes.toBytes("Qualifier"), 1);
787 HTable t = new HTable(conf, TEST_TABLE.getTableName());
788 try {
789 t.increment(inc);
790 } finally {
791 t.close();
792 }
793 return null;
794 }
795 };
796 verifyWrite(incrementAction);
797 }
798
799 @Test
800 public void testReadWrite() throws Exception {
801
802 PrivilegedExceptionAction checkAndDeleteAction = new PrivilegedExceptionAction() {
803 @Override
804 public Object run() throws Exception {
805 Delete d = new Delete(Bytes.toBytes("random_row"));
806 d.deleteFamily(TEST_FAMILY);
807 HTable t = new HTable(conf, TEST_TABLE.getTableName());
808 try {
809 t.checkAndDelete(Bytes.toBytes("random_row"), TEST_FAMILY, Bytes.toBytes("q"),
810 Bytes.toBytes("test_value"), d);
811 } finally {
812 t.close();
813 }
814 return null;
815 }
816 };
817 verifyReadWrite(checkAndDeleteAction);
818
819
820 PrivilegedExceptionAction checkAndPut = new PrivilegedExceptionAction() {
821 @Override
822 public Object run() throws Exception {
823 Put p = new Put(Bytes.toBytes("random_row"));
824 p.add(TEST_FAMILY, Bytes.toBytes("Qualifier"), Bytes.toBytes(1));
825 HTable t = new HTable(conf, TEST_TABLE.getTableName());
826 try {
827 t.checkAndPut(Bytes.toBytes("random_row"), TEST_FAMILY, Bytes.toBytes("q"),
828 Bytes.toBytes("test_value"), p);
829 } finally {
830 t.close();
831 }
832 return null;
833 }
834 };
835 verifyReadWrite(checkAndPut);
836 }
837
838 @Test
839 public void testBulkLoad() throws Exception {
840 FileSystem fs = TEST_UTIL.getTestFileSystem();
841 final Path dir = TEST_UTIL.getDataTestDirOnTestFS("testBulkLoad");
842 fs.mkdirs(dir);
843
844
845 fs.setPermission(dir, FsPermission.valueOf("-rwxrwxrwx"));
846
847 PrivilegedExceptionAction bulkLoadAction = new PrivilegedExceptionAction() {
848 @Override
849 public Object run() throws Exception {
850 int numRows = 3;
851
852
853 byte[][][] hfileRanges = {{{(byte)0}, {(byte)9}}};
854
855 Path bulkLoadBasePath = new Path(dir, new Path(User.getCurrent().getName()));
856 new BulkLoadHelper(bulkLoadBasePath)
857 .bulkLoadHFile(TEST_TABLE.getTableName(), TEST_FAMILY, Bytes.toBytes("q"), hfileRanges, numRows);
858
859 return null;
860 }
861 };
862
863
864
865 verifyAllowed(bulkLoadAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
866 verifyDenied(bulkLoadAction, USER_RW, USER_NONE, USER_RO);
867
868
869 TEST_UTIL.getHBaseAdmin().disableTable(TEST_TABLE.getTableName());
870 TEST_UTIL.getHBaseAdmin().enableTable(TEST_TABLE.getTableName());
871 }
872
873 public class BulkLoadHelper {
874 private final FileSystem fs;
875 private final Path loadPath;
876 private final Configuration conf;
877
878 public BulkLoadHelper(Path loadPath) throws IOException {
879 fs = TEST_UTIL.getTestFileSystem();
880 conf = TEST_UTIL.getConfiguration();
881 loadPath = loadPath.makeQualified(fs);
882 this.loadPath = loadPath;
883 }
884
885 private void createHFile(Path path,
886 byte[] family, byte[] qualifier,
887 byte[] startKey, byte[] endKey, int numRows) throws IOException {
888
889 HFile.Writer writer = null;
890 long now = System.currentTimeMillis();
891 try {
892 writer = HFile.getWriterFactory(conf, new CacheConfig(conf))
893 .withPath(fs, path)
894 .create();
895
896 for (byte[] key : Bytes.iterateOnSplits(startKey, endKey, true, numRows-2)) {
897 KeyValue kv = new KeyValue(key, family, qualifier, now, key);
898 writer.append(kv);
899 }
900 } finally {
901 if(writer != null)
902 writer.close();
903 }
904 }
905
906 private void bulkLoadHFile(
907 TableName tableName,
908 byte[] family,
909 byte[] qualifier,
910 byte[][][] hfileRanges,
911 int numRowsPerRange) throws Exception {
912
913 Path familyDir = new Path(loadPath, Bytes.toString(family));
914 fs.mkdirs(familyDir);
915 int hfileIdx = 0;
916 for (byte[][] range : hfileRanges) {
917 byte[] from = range[0];
918 byte[] to = range[1];
919 createHFile(new Path(familyDir, "hfile_"+(hfileIdx++)),
920 family, qualifier, from, to, numRowsPerRange);
921 }
922
923 setPermission(loadPath, FsPermission.valueOf("-rwxrwxrwx"));
924
925 HTable table = new HTable(conf, tableName);
926 try {
927 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
928 TEST_UTIL.waitTableEnabled(admin, tableName.getName());
929 LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf);
930 loader.doBulkLoad(loadPath, table);
931 } finally {
932 table.close();
933 }
934 }
935
936 public void setPermission(Path dir, FsPermission perm) throws IOException {
937 if(!fs.getFileStatus(dir).isDir()) {
938 fs.setPermission(dir,perm);
939 }
940 else {
941 for(FileStatus el : fs.listStatus(dir)) {
942 fs.setPermission(el.getPath(), perm);
943 setPermission(el.getPath() , perm);
944 }
945 }
946 }
947 }
948
949 @Test
950 public void testAppend() throws Exception {
951
952 PrivilegedExceptionAction appendAction = new PrivilegedExceptionAction() {
953 @Override
954 public Object run() throws Exception {
955 byte[] row = Bytes.toBytes("random_row");
956 byte[] qualifier = Bytes.toBytes("q");
957 Put put = new Put(row);
958 put.add(TEST_FAMILY, qualifier, Bytes.toBytes(1));
959 Append append = new Append(row);
960 append.add(TEST_FAMILY, qualifier, Bytes.toBytes(2));
961 HTable t = new HTable(conf, TEST_TABLE.getTableName());
962 try {
963 t.put(put);
964 t.append(append);
965 } finally {
966 t.close();
967 }
968 return null;
969 }
970 };
971
972 verifyAllowed(appendAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW);
973 verifyDenied(appendAction, USER_RO, USER_NONE);
974 }
975
976 @Test
977 public void testGrantRevoke() throws Exception {
978
979 PrivilegedExceptionAction grantAction = new PrivilegedExceptionAction() {
980 @Override
981 public Object run() throws Exception {
982 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
983 try {
984 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
985 AccessControlService.BlockingInterface protocol =
986 AccessControlService.newBlockingStub(service);
987 ProtobufUtil.grant(protocol, USER_RO.getShortName(), TEST_TABLE.getTableName(),
988 TEST_FAMILY, null, Action.READ);
989 } finally {
990 acl.close();
991 }
992 return null;
993 }
994 };
995
996 PrivilegedExceptionAction revokeAction = new PrivilegedExceptionAction() {
997 @Override
998 public Object run() throws Exception {
999 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1000 try {
1001 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
1002 AccessControlService.BlockingInterface protocol =
1003 AccessControlService.newBlockingStub(service);
1004 ProtobufUtil.revoke(protocol, USER_RO.getShortName(), TEST_TABLE.getTableName(),
1005 TEST_FAMILY, null, Action.READ);
1006 } finally {
1007 acl.close();
1008 }
1009 return null;
1010 }
1011 };
1012
1013 PrivilegedExceptionAction getPermissionsAction = new PrivilegedExceptionAction() {
1014 @Override
1015 public Object run() throws Exception {
1016 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1017 try {
1018 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
1019 AccessControlService.BlockingInterface protocol =
1020 AccessControlService.newBlockingStub(service);
1021 ProtobufUtil.getUserPermissions(protocol, TEST_TABLE.getTableName());
1022 } finally {
1023 acl.close();
1024 }
1025 return null;
1026 }
1027 };
1028
1029 verifyAllowed(grantAction, SUPERUSER, USER_ADMIN, USER_OWNER);
1030 verifyDenied(grantAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
1031
1032 verifyAllowed(revokeAction, SUPERUSER, USER_ADMIN, USER_OWNER);
1033 verifyDenied(revokeAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
1034
1035 verifyAllowed(getPermissionsAction, SUPERUSER, USER_ADMIN, USER_OWNER);
1036 verifyDenied(getPermissionsAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
1037 }
1038
1039 @Test
1040 public void testPostGrantRevoke() throws Exception {
1041 final TableName tableName =
1042 TableName.valueOf("TempTable");
1043 final byte[] family1 = Bytes.toBytes("f1");
1044 final byte[] family2 = Bytes.toBytes("f2");
1045 final byte[] qualifier = Bytes.toBytes("q");
1046
1047
1048 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
1049 if (admin.tableExists(tableName)) {
1050 admin.disableTable(tableName);
1051 admin.deleteTable(tableName);
1052 }
1053 HTableDescriptor htd = new HTableDescriptor(tableName);
1054 htd.addFamily(new HColumnDescriptor(family1));
1055 htd.addFamily(new HColumnDescriptor(family2));
1056 admin.createTable(htd);
1057
1058
1059 User tblUser = User
1060 .createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser", new String[0]);
1061 User gblUser = User
1062 .createUserForTesting(TEST_UTIL.getConfiguration(), "gbluser", new String[0]);
1063
1064
1065 PrivilegedExceptionAction putActionAll = new PrivilegedExceptionAction() {
1066 @Override
1067 public Object run() throws Exception {
1068 Put p = new Put(Bytes.toBytes("a"));
1069 p.add(family1, qualifier, Bytes.toBytes("v1"));
1070 p.add(family2, qualifier, Bytes.toBytes("v2"));
1071 HTable t = new HTable(conf, tableName);
1072 try {
1073 t.put(p);
1074 } finally {
1075 t.close();
1076 }
1077 return null;
1078 }
1079 };
1080 PrivilegedExceptionAction putAction1 = new PrivilegedExceptionAction() {
1081 @Override
1082 public Object run() throws Exception {
1083 Put p = new Put(Bytes.toBytes("a"));
1084 p.add(family1, qualifier, Bytes.toBytes("v1"));
1085 HTable t = new HTable(conf, tableName);
1086 try {
1087 t.put(p);
1088 } finally {
1089 t.close();
1090 }
1091 return null;
1092 }
1093 };
1094 PrivilegedExceptionAction putAction2 = new PrivilegedExceptionAction() {
1095 @Override
1096 public Object run() throws Exception {
1097 Put p = new Put(Bytes.toBytes("a"));
1098 p.add(family2, qualifier, Bytes.toBytes("v2"));
1099 HTable t = new HTable(conf, tableName);
1100 try {
1101 t.put(p);
1102 } finally {
1103 t.close();
1104 }
1105 return null;
1106 }
1107 };
1108 PrivilegedExceptionAction getActionAll = new PrivilegedExceptionAction() {
1109 @Override
1110 public Object run() throws Exception {
1111 Get g = new Get(Bytes.toBytes("random_row"));
1112 g.addFamily(family1);
1113 g.addFamily(family2);
1114 HTable t = new HTable(conf, tableName);
1115 try {
1116 t.get(g);
1117 } finally {
1118 t.close();
1119 }
1120 return null;
1121 }
1122 };
1123 PrivilegedExceptionAction getAction1 = new PrivilegedExceptionAction() {
1124 @Override
1125 public Object run() throws Exception {
1126 Get g = new Get(Bytes.toBytes("random_row"));
1127 g.addFamily(family1);
1128 HTable t = new HTable(conf, tableName);
1129 try {
1130 t.get(g);
1131 } finally {
1132 t.close();
1133 }
1134 return null;
1135 }
1136 };
1137 PrivilegedExceptionAction getAction2 = new PrivilegedExceptionAction() {
1138 @Override
1139 public Object run() throws Exception {
1140 Get g = new Get(Bytes.toBytes("random_row"));
1141 g.addFamily(family2);
1142 HTable t = new HTable(conf, tableName);
1143 try {
1144 t.get(g);
1145 } finally {
1146 t.close();
1147 }
1148 return null;
1149 }
1150 };
1151 PrivilegedExceptionAction deleteActionAll = new PrivilegedExceptionAction() {
1152 @Override
1153 public Object run() throws Exception {
1154 Delete d = new Delete(Bytes.toBytes("random_row"));
1155 d.deleteFamily(family1);
1156 d.deleteFamily(family2);
1157 HTable t = new HTable(conf, tableName);
1158 try {
1159 t.delete(d);
1160 } finally {
1161 t.close();
1162 }
1163 return null;
1164 }
1165 };
1166 PrivilegedExceptionAction deleteAction1 = new PrivilegedExceptionAction() {
1167 @Override
1168 public Object run() throws Exception {
1169 Delete d = new Delete(Bytes.toBytes("random_row"));
1170 d.deleteFamily(family1);
1171 HTable t = new HTable(conf, tableName);
1172 try {
1173 t.delete(d);
1174 } finally {
1175 t.close();
1176 }
1177 return null;
1178 }
1179 };
1180 PrivilegedExceptionAction deleteAction2 = new PrivilegedExceptionAction() {
1181 @Override
1182 public Object run() throws Exception {
1183 Delete d = new Delete(Bytes.toBytes("random_row"));
1184 d.deleteFamily(family2);
1185 HTable t = new HTable(conf, tableName);
1186 try {
1187 t.delete(d);
1188 } finally {
1189 t.close();
1190 }
1191 return null;
1192 }
1193 };
1194
1195
1196 verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1197 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1198 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1199
1200 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1201 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1202 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1203
1204
1205 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1206 try {
1207 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1208 AccessControlService.BlockingInterface protocol =
1209 AccessControlService.newBlockingStub(service);
1210 ProtobufUtil.grant(protocol, tblUser.getShortName(),
1211 tableName, null, null, Permission.Action.READ);
1212 ProtobufUtil.grant(protocol, gblUser.getShortName(),
1213 Permission.Action.READ);
1214 } finally {
1215 acl.close();
1216 }
1217
1218 Thread.sleep(100);
1219
1220 verifyAllowed(tblUser, getActionAll, getAction1, getAction2);
1221 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1222 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1223
1224 verifyAllowed(gblUser, getActionAll, getAction1, getAction2);
1225 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1226 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1227
1228
1229 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1230 try {
1231 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1232 AccessControlService.BlockingInterface protocol =
1233 AccessControlService.newBlockingStub(service);
1234 ProtobufUtil.grant(protocol, tblUser.getShortName(),
1235 tableName, null, null, Permission.Action.WRITE);
1236 ProtobufUtil.grant(protocol, gblUser.getShortName(),
1237 Permission.Action.WRITE);
1238 } finally {
1239 acl.close();
1240 }
1241
1242 Thread.sleep(100);
1243
1244 verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1245 verifyAllowed(tblUser, putActionAll, putAction1, putAction2);
1246 verifyAllowed(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1247
1248 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1249 verifyAllowed(gblUser, putActionAll, putAction1, putAction2);
1250 verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1251
1252
1253 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1254 try {
1255 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1256 AccessControlService.BlockingInterface protocol =
1257 AccessControlService.newBlockingStub(service);
1258 ProtobufUtil.grant(protocol, tblUser.getShortName(), tableName, null, null,
1259 Permission.Action.READ, Permission.Action.WRITE);
1260 ProtobufUtil.revoke(protocol, tblUser.getShortName(), tableName, null, null);
1261 ProtobufUtil.revoke(protocol, gblUser.getShortName());
1262 } finally {
1263 acl.close();
1264 }
1265
1266 Thread.sleep(100);
1267
1268 verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1269 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1270 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1271
1272 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1273 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1274 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1275
1276
1277 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1278 try {
1279 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1280 AccessControlService.BlockingInterface protocol =
1281 AccessControlService.newBlockingStub(service);
1282 ProtobufUtil.grant(protocol, tblUser.getShortName(),
1283 tableName, family1, null, Permission.Action.READ);
1284 ProtobufUtil.grant(protocol, gblUser.getShortName(),
1285 Permission.Action.READ);
1286 } finally {
1287 acl.close();
1288 }
1289
1290 Thread.sleep(100);
1291
1292
1293 verifyAllowed(tblUser, getActionAll, getAction1);
1294 verifyDenied(tblUser, getAction2);
1295 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1296 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1297
1298 verifyAllowed(gblUser, getActionAll, getAction1, getAction2);
1299 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1300 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1301
1302
1303 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1304 try {
1305 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1306 AccessControlService.BlockingInterface protocol =
1307 AccessControlService.newBlockingStub(service);
1308 ProtobufUtil.grant(protocol, tblUser.getShortName(),
1309 tableName, family2, null, Permission.Action.WRITE);
1310 ProtobufUtil.grant(protocol, gblUser.getShortName(),
1311 Permission.Action.WRITE);
1312 } finally {
1313 acl.close();
1314 }
1315
1316 Thread.sleep(100);
1317
1318
1319 verifyAllowed(tblUser, getActionAll, getAction1);
1320 verifyAllowed(tblUser, putAction2, deleteAction2);
1321 verifyDenied(tblUser, getAction2);
1322 verifyDenied(tblUser, putActionAll, putAction1);
1323 verifyDenied(tblUser, deleteActionAll, deleteAction1);
1324
1325 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1326 verifyAllowed(gblUser, putActionAll, putAction1, putAction2);
1327 verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1328
1329
1330 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1331 try {
1332 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1333 AccessControlService.BlockingInterface protocol =
1334 AccessControlService.newBlockingStub(service);
1335 ProtobufUtil.revoke(protocol, tblUser.getShortName(), tableName, family2, null);
1336 ProtobufUtil.revoke(protocol, gblUser.getShortName());
1337 } finally {
1338 acl.close();
1339 }
1340
1341 Thread.sleep(100);
1342
1343
1344 verifyAllowed(tblUser, getActionAll, getAction1);
1345 verifyDenied(tblUser, getAction2);
1346 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1347 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1348
1349
1350 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1351 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1352 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1353
1354
1355 admin.disableTable(tableName);
1356 admin.deleteTable(tableName);
1357 }
1358
1359 private boolean hasFoundUserPermission(UserPermission userPermission, List<UserPermission> perms) {
1360 return perms.contains(userPermission);
1361 }
1362
1363 @Test
1364 public void testPostGrantRevokeAtQualifierLevel() throws Exception {
1365 final TableName tableName =
1366 TableName.valueOf("testGrantRevokeAtQualifierLevel");
1367 final byte[] family1 = Bytes.toBytes("f1");
1368 final byte[] family2 = Bytes.toBytes("f2");
1369 final byte[] qualifier = Bytes.toBytes("q");
1370
1371
1372 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
1373 if (admin.tableExists(tableName)) {
1374 admin.disableTable(tableName);
1375 admin.deleteTable(tableName);
1376 }
1377 HTableDescriptor htd = new HTableDescriptor(tableName);
1378 htd.addFamily(new HColumnDescriptor(family1));
1379 htd.addFamily(new HColumnDescriptor(family2));
1380 admin.createTable(htd);
1381
1382
1383 User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]);
1384
1385 PrivilegedExceptionAction getQualifierAction = new PrivilegedExceptionAction() {
1386 @Override
1387 public Object run() throws Exception {
1388 Get g = new Get(Bytes.toBytes("random_row"));
1389 g.addColumn(family1, qualifier);
1390 HTable t = new HTable(conf, tableName);
1391 try {
1392 t.get(g);
1393 } finally {
1394 t.close();
1395 }
1396 return null;
1397 }
1398 };
1399 PrivilegedExceptionAction putQualifierAction = new PrivilegedExceptionAction() {
1400 @Override
1401 public Object run() throws Exception {
1402 Put p = new Put(Bytes.toBytes("random_row"));
1403 p.add(family1, qualifier, Bytes.toBytes("v1"));
1404 HTable t = new HTable(conf, tableName);
1405 try {
1406 t.put(p);
1407 } finally {
1408 t.close();
1409 }
1410 return null;
1411 }
1412 };
1413 PrivilegedExceptionAction deleteQualifierAction = new PrivilegedExceptionAction() {
1414 @Override
1415 public Object run() throws Exception {
1416 Delete d = new Delete(Bytes.toBytes("random_row"));
1417 d.deleteColumn(family1, qualifier);
1418
1419 HTable t = new HTable(conf, tableName);
1420 try {
1421 t.delete(d);
1422 } finally {
1423 t.close();
1424 }
1425 return null;
1426 }
1427 };
1428
1429 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1430 try {
1431 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1432 AccessControlService.BlockingInterface protocol =
1433 AccessControlService.newBlockingStub(service);
1434 ProtobufUtil.revoke(protocol, user.getShortName(), tableName, family1, null);
1435 } finally {
1436 acl.close();
1437 }
1438
1439 Thread.sleep(100);
1440
1441 verifyDenied(user, getQualifierAction);
1442 verifyDenied(user, putQualifierAction);
1443 verifyDenied(user, deleteQualifierAction);
1444
1445 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1446 try {
1447 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1448 AccessControlService.BlockingInterface protocol =
1449 AccessControlService.newBlockingStub(service);
1450 ProtobufUtil.grant(protocol, user.getShortName(),
1451 tableName, family1, qualifier, Permission.Action.READ);
1452 } finally {
1453 acl.close();
1454 }
1455
1456 Thread.sleep(100);
1457
1458 verifyAllowed(user, getQualifierAction);
1459 verifyDenied(user, putQualifierAction);
1460 verifyDenied(user, deleteQualifierAction);
1461
1462
1463
1464 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1465 try {
1466 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1467 AccessControlService.BlockingInterface protocol =
1468 AccessControlService.newBlockingStub(service);
1469 ProtobufUtil.grant(protocol, user.getShortName(),
1470 tableName, family1, qualifier, Permission.Action.WRITE);
1471 } finally {
1472 acl.close();
1473 }
1474
1475 Thread.sleep(100);
1476
1477 verifyDenied(user, getQualifierAction);
1478 verifyAllowed(user, putQualifierAction);
1479 verifyAllowed(user, deleteQualifierAction);
1480
1481
1482 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1483 try {
1484 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1485 AccessControlService.BlockingInterface protocol =
1486 AccessControlService.newBlockingStub(service);
1487 ProtobufUtil.grant(protocol, user.getShortName(),
1488 tableName, family1, qualifier,
1489 Permission.Action.READ, Permission.Action.WRITE);
1490 } finally {
1491 acl.close();
1492 }
1493
1494 Thread.sleep(100);
1495
1496 verifyAllowed(user, getQualifierAction);
1497 verifyAllowed(user, putQualifierAction);
1498 verifyAllowed(user, deleteQualifierAction);
1499
1500
1501 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1502 try {
1503 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1504 AccessControlService.BlockingInterface protocol =
1505 AccessControlService.newBlockingStub(service);
1506 ProtobufUtil.revoke(protocol, user.getShortName(),
1507 tableName, family1, qualifier);
1508 } finally {
1509 acl.close();
1510 }
1511
1512 Thread.sleep(100);
1513
1514 verifyDenied(user, getQualifierAction);
1515 verifyDenied(user, putQualifierAction);
1516 verifyDenied(user, deleteQualifierAction);
1517
1518
1519 admin.disableTable(tableName);
1520 admin.deleteTable(tableName);
1521 }
1522
1523 @Test
1524 public void testPermissionList() throws Exception {
1525 final TableName tableName =
1526 TableName.valueOf("testPermissionList");
1527 final byte[] family1 = Bytes.toBytes("f1");
1528 final byte[] family2 = Bytes.toBytes("f2");
1529 final byte[] qualifier = Bytes.toBytes("q");
1530
1531
1532 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
1533 if (admin.tableExists(tableName)) {
1534 admin.disableTable(tableName);
1535 admin.deleteTable(tableName);
1536 }
1537 HTableDescriptor htd = new HTableDescriptor(tableName);
1538 htd.addFamily(new HColumnDescriptor(family1));
1539 htd.addFamily(new HColumnDescriptor(family2));
1540 htd.setOwner(USER_OWNER);
1541 admin.createTable(htd);
1542
1543 List<UserPermission> perms;
1544
1545 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1546 try {
1547 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1548 AccessControlService.BlockingInterface protocol =
1549 AccessControlService.newBlockingStub(service);
1550 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1551 } finally {
1552 acl.close();
1553 }
1554
1555 UserPermission ownerperm = new UserPermission(
1556 Bytes.toBytes(USER_OWNER.getName()), tableName, null, Action.values());
1557 assertTrue("Owner should have all permissions on table",
1558 hasFoundUserPermission(ownerperm, perms));
1559
1560 User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]);
1561 byte[] userName = Bytes.toBytes(user.getShortName());
1562
1563 UserPermission up = new UserPermission(userName,
1564 tableName, family1, qualifier, Permission.Action.READ);
1565 assertFalse("User should not be granted permission: " + up.toString(),
1566 hasFoundUserPermission(up, perms));
1567
1568
1569 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1570 try {
1571 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1572 AccessControlService.BlockingInterface protocol =
1573 AccessControlService.newBlockingStub(service);
1574 ProtobufUtil.grant(protocol, user.getShortName(),
1575 tableName, family1, qualifier, Permission.Action.READ);
1576 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1577 } finally {
1578 acl.close();
1579 }
1580
1581 UserPermission upToVerify = new UserPermission(
1582 userName, tableName, family1, qualifier, Permission.Action.READ);
1583 assertTrue("User should be granted permission: " + upToVerify.toString(),
1584 hasFoundUserPermission(upToVerify, perms));
1585
1586 upToVerify = new UserPermission(
1587 userName, tableName, family1, qualifier, Permission.Action.WRITE);
1588 assertFalse("User should not be granted permission: " + upToVerify.toString(),
1589 hasFoundUserPermission(upToVerify, perms));
1590
1591
1592 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1593 try {
1594 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1595 AccessControlService.BlockingInterface protocol =
1596 AccessControlService.newBlockingStub(service);
1597 ProtobufUtil.grant(protocol, user.getShortName(),
1598 tableName, family1, qualifier,
1599 Permission.Action.WRITE, Permission.Action.READ);
1600 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1601 } finally {
1602 acl.close();
1603 }
1604
1605 upToVerify = new UserPermission(userName, tableName, family1,
1606 qualifier, Permission.Action.WRITE, Permission.Action.READ);
1607 assertTrue("User should be granted permission: " + upToVerify.toString(),
1608 hasFoundUserPermission(upToVerify, perms));
1609
1610 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1611 try {
1612 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1613 AccessControlService.BlockingInterface protocol =
1614 AccessControlService.newBlockingStub(service);
1615 ProtobufUtil.revoke(protocol, user.getShortName(), tableName, family1, qualifier,
1616 Permission.Action.WRITE, Permission.Action.READ);
1617 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1618 } finally {
1619 acl.close();
1620 }
1621
1622 assertFalse("User should not be granted permission: " + upToVerify.toString(),
1623 hasFoundUserPermission(upToVerify, perms));
1624
1625
1626 admin.disableTable(tableName);
1627
1628 User newOwner = User.createUserForTesting(conf, "new_owner", new String[] {});
1629 htd.setOwner(newOwner);
1630 admin.modifyTable(tableName, htd);
1631
1632 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1633 try {
1634 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1635 AccessControlService.BlockingInterface protocol =
1636 AccessControlService.newBlockingStub(service);
1637 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1638 } finally {
1639 acl.close();
1640 }
1641
1642 UserPermission newOwnerperm = new UserPermission(
1643 Bytes.toBytes(newOwner.getName()), tableName, null, Action.values());
1644 assertTrue("New owner should have all permissions on table",
1645 hasFoundUserPermission(newOwnerperm, perms));
1646
1647
1648 admin.deleteTable(tableName);
1649 }
1650
1651 @Test
1652 public void testGlobalPermissionList() throws Exception {
1653 List<UserPermission> perms;
1654 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1655 try {
1656 BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
1657 AccessControlService.BlockingInterface protocol =
1658 AccessControlService.newBlockingStub(service);
1659 perms = ProtobufUtil.getUserPermissions(protocol);
1660 } finally {
1661 acl.close();
1662 }
1663 UserPermission adminPerm = new UserPermission(Bytes.toBytes(USER_ADMIN.getShortName()),
1664 AccessControlLists.ACL_TABLE_NAME, null, null, Bytes.toBytes("ACRW"));
1665 assertTrue("Only user admin has permission on table _acl_ per setup",
1666 perms.size() == 1 && hasFoundUserPermission(adminPerm, perms));
1667 }
1668
1669
1670 private void verifyGlobal(PrivilegedExceptionAction<?> action) throws Exception {
1671 verifyAllowed(action, SUPERUSER);
1672
1673 verifyDenied(action, USER_CREATE, USER_RW, USER_NONE, USER_RO);
1674 }
1675
1676 public void checkGlobalPerms(Permission.Action... actions) throws IOException {
1677 Permission[] perms = new Permission[actions.length];
1678 for (int i = 0; i < actions.length; i++) {
1679 perms[i] = new Permission(actions[i]);
1680 }
1681 CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
1682 for (Action a : actions) {
1683 request.addPermission(AccessControlProtos.Permission.newBuilder()
1684 .setType(AccessControlProtos.Permission.Type.Global)
1685 .setGlobalPermission(
1686 AccessControlProtos.GlobalPermission.newBuilder()
1687 .addAction(ProtobufUtil.toPermissionAction(a)).build()));
1688 }
1689 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1690 try {
1691 BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
1692 AccessControlService.BlockingInterface protocol =
1693 AccessControlService.newBlockingStub(channel);
1694 try {
1695 protocol.checkPermissions(null, request.build());
1696 } catch (ServiceException se) {
1697 ProtobufUtil.toIOException(se);
1698 }
1699 } finally {
1700 acl.close();
1701 }
1702 }
1703
1704 public void checkTablePerms(TableName table, byte[] family, byte[] column,
1705 Permission.Action... actions) throws IOException {
1706 Permission[] perms = new Permission[actions.length];
1707 for (int i = 0; i < actions.length; i++) {
1708 perms[i] = new TablePermission(table, family, column, actions[i]);
1709 }
1710
1711 checkTablePerms(table, perms);
1712 }
1713
1714 public void checkTablePerms(TableName table, Permission... perms) throws IOException {
1715 CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
1716 for (Permission p : perms) {
1717 request.addPermission(ProtobufUtil.toPermission(p));
1718 }
1719 HTable acl = new HTable(conf, table);
1720 try {
1721 AccessControlService.BlockingInterface protocol =
1722 AccessControlService.newBlockingStub(acl.coprocessorService(new byte[0]));
1723 try {
1724 protocol.checkPermissions(null, request.build());
1725 } catch (ServiceException se) {
1726 ProtobufUtil.toIOException(se);
1727 }
1728 } finally {
1729 acl.close();
1730 }
1731 }
1732
1733 @Test
1734 public void testCheckPermissions() throws Exception {
1735
1736
1737 PrivilegedExceptionAction<Void> globalAdmin = new PrivilegedExceptionAction<Void>() {
1738 @Override
1739 public Void run() throws Exception {
1740 checkGlobalPerms(Permission.Action.ADMIN);
1741 return null;
1742 }
1743 };
1744
1745 verifyGlobal(globalAdmin);
1746
1747
1748
1749 PrivilegedExceptionAction<Void> globalReadWrite = new PrivilegedExceptionAction<Void>() {
1750 @Override
1751 public Void run() throws Exception {
1752 checkGlobalPerms(Permission.Action.READ, Permission.Action.WRITE);
1753 return null;
1754 }
1755 };
1756
1757 verifyGlobal(globalReadWrite);
1758
1759
1760
1761 final byte[] TEST_Q1 = Bytes.toBytes("q1");
1762 final byte[] TEST_Q2 = Bytes.toBytes("q2");
1763
1764 User userTable = User.createUserForTesting(conf, "user_check_perms_table", new String[0]);
1765 User userColumn = User.createUserForTesting(conf, "user_check_perms_family", new String[0]);
1766 User userQualifier = User.createUserForTesting(conf, "user_check_perms_q", new String[0]);
1767
1768 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1769 try {
1770 BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
1771 AccessControlService.BlockingInterface protocol =
1772 AccessControlService.newBlockingStub(channel);
1773 ProtobufUtil.grant(protocol, userTable.getShortName(),
1774 TEST_TABLE.getTableName(), null, null, Permission.Action.READ);
1775 ProtobufUtil.grant(protocol, userColumn.getShortName(),
1776 TEST_TABLE.getTableName(), TEST_FAMILY, null, Permission.Action.READ);
1777 ProtobufUtil.grant(protocol, userQualifier.getShortName(),
1778 TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1, Permission.Action.READ);
1779 } finally {
1780 acl.close();
1781 }
1782
1783 PrivilegedExceptionAction<Void> tableRead = new PrivilegedExceptionAction<Void>() {
1784 @Override
1785 public Void run() throws Exception {
1786 checkTablePerms(TEST_TABLE.getTableName(), null, null, Permission.Action.READ);
1787 return null;
1788 }
1789 };
1790
1791 PrivilegedExceptionAction<Void> columnRead = new PrivilegedExceptionAction<Void>() {
1792 @Override
1793 public Void run() throws Exception {
1794 checkTablePerms(TEST_TABLE.getTableName(), TEST_FAMILY, null, Permission.Action.READ);
1795 return null;
1796 }
1797 };
1798
1799 PrivilegedExceptionAction<Void> qualifierRead = new PrivilegedExceptionAction<Void>() {
1800 @Override
1801 public Void run() throws Exception {
1802 checkTablePerms(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1, Permission.Action.READ);
1803 return null;
1804 }
1805 };
1806
1807 PrivilegedExceptionAction<Void> multiQualifierRead = new PrivilegedExceptionAction<Void>() {
1808 @Override
1809 public Void run() throws Exception {
1810 checkTablePerms(TEST_TABLE.getTableName(), new Permission[] {
1811 new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1, Permission.Action.READ),
1812 new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q2, Permission.Action.READ), });
1813 return null;
1814 }
1815 };
1816
1817 PrivilegedExceptionAction<Void> globalAndTableRead = new PrivilegedExceptionAction<Void>() {
1818 @Override
1819 public Void run() throws Exception {
1820 checkTablePerms(TEST_TABLE.getTableName(), new Permission[] { new Permission(Permission.Action.READ),
1821 new TablePermission(TEST_TABLE.getTableName(), null, (byte[]) null, Permission.Action.READ), });
1822 return null;
1823 }
1824 };
1825
1826 PrivilegedExceptionAction<Void> noCheck = new PrivilegedExceptionAction<Void>() {
1827 @Override
1828 public Void run() throws Exception {
1829 checkTablePerms(TEST_TABLE.getTableName(), new Permission[0]);
1830 return null;
1831 }
1832 };
1833
1834 verifyAllowed(tableRead, SUPERUSER, userTable);
1835 verifyDenied(tableRead, userColumn, userQualifier);
1836
1837 verifyAllowed(columnRead, SUPERUSER, userTable, userColumn);
1838 verifyDenied(columnRead, userQualifier);
1839
1840 verifyAllowed(qualifierRead, SUPERUSER, userTable, userColumn, userQualifier);
1841
1842 verifyAllowed(multiQualifierRead, SUPERUSER, userTable, userColumn);
1843 verifyDenied(multiQualifierRead, userQualifier);
1844
1845 verifyAllowed(globalAndTableRead, SUPERUSER);
1846 verifyDenied(globalAndTableRead, userTable, userColumn, userQualifier);
1847
1848 verifyAllowed(noCheck, SUPERUSER, userTable, userColumn, userQualifier);
1849
1850
1851
1852 PrivilegedExceptionAction<Void> familyReadWrite = new PrivilegedExceptionAction<Void>() {
1853 @Override
1854 public Void run() throws Exception {
1855 checkTablePerms(TEST_TABLE.getTableName(), TEST_FAMILY, null, Permission.Action.READ,
1856 Permission.Action.WRITE);
1857 return null;
1858 }
1859 };
1860
1861 verifyAllowed(familyReadWrite, SUPERUSER, USER_OWNER, USER_CREATE, USER_RW);
1862 verifyDenied(familyReadWrite, USER_NONE, USER_RO);
1863
1864
1865
1866 CheckPermissionsRequest checkRequest = CheckPermissionsRequest.newBuilder()
1867 .addPermission(AccessControlProtos.Permission.newBuilder()
1868 .setType(AccessControlProtos.Permission.Type.Table)
1869 .setTablePermission(
1870 AccessControlProtos.TablePermission.newBuilder()
1871 .setTableName(ProtobufUtil.toProtoTableName(TEST_TABLE.getTableName()))
1872 .addAction(AccessControlProtos.Permission.Action.CREATE))
1873 ).build();
1874 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1875 try {
1876 BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
1877 AccessControlService.BlockingInterface protocol =
1878 AccessControlService.newBlockingStub(channel);
1879 try {
1880
1881 protocol.checkPermissions(null, checkRequest);
1882 fail("this should have thrown CoprocessorException");
1883 } catch (ServiceException ex) {
1884
1885 }
1886 } finally {
1887 acl.close();
1888 }
1889 }
1890
1891 @Test
1892 public void testStopRegionServer() throws Exception {
1893 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
1894 @Override
1895 public Object run() throws Exception {
1896 ACCESS_CONTROLLER.preStopRegionServer(ObserverContext.createAndPrepare(RSCP_ENV, null));
1897 return null;
1898 }
1899 };
1900
1901 verifyAllowed(action, SUPERUSER, USER_ADMIN);
1902 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
1903 }
1904
1905 @Test
1906 public void testOpenRegion() throws Exception {
1907 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
1908 @Override
1909 public Object run() throws Exception {
1910 ACCESS_CONTROLLER.preOpen(ObserverContext.createAndPrepare(RCP_ENV, null));
1911 return null;
1912 }
1913 };
1914
1915 verifyAllowed(action, SUPERUSER, USER_ADMIN);
1916 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1917 }
1918
1919 @Test
1920 public void testCloseRegion() throws Exception {
1921 PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
1922 @Override
1923 public Object run() throws Exception {
1924 ACCESS_CONTROLLER.preClose(ObserverContext.createAndPrepare(RCP_ENV, null), false);
1925 return null;
1926 }
1927 };
1928
1929 verifyAllowed(action, SUPERUSER, USER_ADMIN);
1930 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1931 }
1932
1933 @Test
1934 public void testSnapshot() throws Exception {
1935 PrivilegedExceptionAction snapshotAction = new PrivilegedExceptionAction() {
1936 @Override
1937 public Object run() throws Exception {
1938 ACCESS_CONTROLLER.preSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1939 null, null);
1940 return null;
1941 }
1942 };
1943
1944 PrivilegedExceptionAction deleteAction = new PrivilegedExceptionAction() {
1945 @Override
1946 public Object run() throws Exception {
1947 ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1948 null);
1949 return null;
1950 }
1951 };
1952
1953 PrivilegedExceptionAction restoreAction = new PrivilegedExceptionAction() {
1954 @Override
1955 public Object run() throws Exception {
1956 ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1957 null, null);
1958 return null;
1959 }
1960 };
1961
1962 PrivilegedExceptionAction cloneAction = new PrivilegedExceptionAction() {
1963 @Override
1964 public Object run() throws Exception {
1965 ACCESS_CONTROLLER.preCloneSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1966 null, null);
1967 return null;
1968 }
1969 };
1970
1971 verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN);
1972 verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1973
1974 verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN);
1975 verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1976
1977 verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN);
1978 verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1979
1980 verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN);
1981 verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1982 }
1983
1984 @Test
1985 public void testGlobalAuthorizationForNewRegisteredRS() throws Exception {
1986 LOG.debug("Test for global authorization for a new registered RegionServer.");
1987 MiniHBaseCluster hbaseCluster = TEST_UTIL.getHBaseCluster();
1988
1989
1990
1991 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1992 try {
1993 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
1994 AccessControlService.BlockingInterface protocol =
1995 AccessControlService.newBlockingStub(service);
1996 String currentUser = User.getCurrent().getShortName();
1997
1998 String activeUserForNewRs = currentUser + ".hfs."
1999 + hbaseCluster.getLiveRegionServerThreads().size();
2000 ProtobufUtil.grant(protocol, activeUserForNewRs,
2001 Permission.Action.ADMIN, Permission.Action.CREATE,
2002 Permission.Action.READ, Permission.Action.WRITE);
2003 } finally {
2004 acl.close();
2005 }
2006 final HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
2007 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE2);
2008 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
2009 admin.createTable(htd);
2010
2011
2012 JVMClusterUtil.RegionServerThread newRsThread = hbaseCluster
2013 .startRegionServer();
2014 final HRegionServer newRs = newRsThread.getRegionServer();
2015
2016
2017 final HTable table = new HTable(TEST_UTIL.getConfiguration(), TEST_TABLE2);
2018 try {
2019 NavigableMap<HRegionInfo, ServerName> regions = table
2020 .getRegionLocations();
2021 final Map.Entry<HRegionInfo, ServerName> firstRegion = regions.entrySet()
2022 .iterator().next();
2023
2024 PrivilegedExceptionAction moveAction = new PrivilegedExceptionAction() {
2025 @Override
2026 public Object run() throws Exception {
2027 admin.move(firstRegion.getKey().getEncodedNameAsBytes(),
2028 Bytes.toBytes(newRs.getServerName().getServerName()));
2029 return null;
2030 }
2031 };
2032 SUPERUSER.runAs(moveAction);
2033
2034 final int RETRIES_LIMIT = 10;
2035 int retries = 0;
2036 while (newRs.getOnlineRegions(TEST_TABLE2).size() < 1 && retries < RETRIES_LIMIT) {
2037 LOG.debug("Waiting for region to be opened. Already retried " + retries
2038 + " times.");
2039 try {
2040 Thread.sleep(1000);
2041 } catch (InterruptedException e) {
2042 }
2043 retries++;
2044 if (retries == RETRIES_LIMIT - 1) {
2045 fail("Retry exhaust for waiting region to be opened.");
2046 }
2047 }
2048
2049
2050 PrivilegedExceptionAction putAction = new PrivilegedExceptionAction() {
2051 @Override
2052 public Object run() throws Exception {
2053 Put put = new Put(Bytes.toBytes("test"));
2054 put.add(TEST_FAMILY, Bytes.toBytes("qual"), Bytes.toBytes("value"));
2055 table.put(put);
2056 return null;
2057 }
2058 };
2059 USER_ADMIN.runAs(putAction);
2060 } finally {
2061 table.close();
2062 }
2063 }
2064
2065 @Test
2066 public void testTableDescriptorsEnumeration() throws Exception {
2067 User TABLE_ADMIN = User.createUserForTesting(conf, "UserA", new String[0]);
2068
2069
2070 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
2071 try {
2072 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
2073 AccessControlService.BlockingInterface protocol =
2074 AccessControlService.newBlockingStub(service);
2075 ProtobufUtil.grant(protocol, TABLE_ADMIN.getShortName(), TEST_TABLE.getTableName(),
2076 null, null, Permission.Action.ADMIN);
2077 } finally {
2078 acl.close();
2079 }
2080
2081 PrivilegedExceptionAction listTablesAction = new PrivilegedExceptionAction() {
2082 @Override
2083 public Object run() throws Exception {
2084 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
2085 try {
2086 admin.listTables();
2087 } finally {
2088 admin.close();
2089 }
2090 return null;
2091 }
2092 };
2093
2094 PrivilegedExceptionAction getTableDescAction = new PrivilegedExceptionAction() {
2095 @Override
2096 public Object run() throws Exception {
2097 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
2098 try {
2099 admin.getTableDescriptor(TEST_TABLE.getTableName());
2100 } finally {
2101 admin.close();
2102 }
2103 return null;
2104 }
2105 };
2106
2107 verifyAllowed(listTablesAction, SUPERUSER, USER_ADMIN);
2108 verifyDenied(listTablesAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, TABLE_ADMIN);
2109
2110 verifyAllowed(getTableDescAction, SUPERUSER, USER_ADMIN, USER_CREATE, TABLE_ADMIN);
2111 verifyDenied(getTableDescAction, USER_RW, USER_RO, USER_NONE);
2112 }
2113
2114 @Test
2115 public void testTableDeletion() throws Exception {
2116 User TABLE_ADMIN = User.createUserForTesting(conf, "TestUser", new String[0]);
2117
2118
2119 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
2120 try {
2121 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
2122 AccessControlService.BlockingInterface protocol =
2123 AccessControlService.newBlockingStub(service);
2124 ProtobufUtil.grant(protocol, TABLE_ADMIN.getShortName(), TEST_TABLE.getTableName(),
2125 null, null, Permission.Action.ADMIN);
2126 } finally {
2127 acl.close();
2128 }
2129
2130 PrivilegedExceptionAction deleteTableAction = new PrivilegedExceptionAction() {
2131 @Override
2132 public Object run() throws Exception {
2133 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
2134 try {
2135 admin.disableTable(TEST_TABLE.getTableName());
2136 admin.deleteTable(TEST_TABLE.getTableName());
2137 } finally {
2138 admin.close();
2139 }
2140 return null;
2141 }
2142 };
2143
2144 verifyDenied(deleteTableAction, USER_RW, USER_RO, USER_NONE);
2145 verifyAllowed(deleteTableAction, TABLE_ADMIN);
2146 }
2147
2148 }