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