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