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