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