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 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.waitTableEnabled(TEST_TABLE.getTableName().getName());
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);
347 verifyDenied(truncateTable, USER_RW, USER_RO, USER_NONE, USER_OWNER);
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 @Test
676 public void testPreCompactSelection() throws Exception {
677 AccessTestAction action = new AccessTestAction() {
678 @Override
679 public Object run() throws Exception {
680 ACCESS_CONTROLLER.preCompactSelection(ObserverContext.createAndPrepare(RCP_ENV, null), null, null);
681 return null;
682 }
683 };
684
685 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
686 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
687 }
688
689 private void verifyRead(AccessTestAction action) throws Exception {
690 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO);
691 verifyDenied(action, USER_NONE);
692 }
693
694 private void verifyReadWrite(AccessTestAction action) throws Exception {
695 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW);
696 verifyDenied(action, USER_NONE, USER_RO);
697 }
698
699 @Test
700 public void testRead() throws Exception {
701
702 AccessTestAction getAction = new AccessTestAction() {
703 @Override
704 public Object run() throws Exception {
705 Get g = new Get(TEST_ROW);
706 g.addFamily(TEST_FAMILY);
707 HTable t = new HTable(conf, TEST_TABLE.getTableName());
708 try {
709 t.get(g);
710 } finally {
711 t.close();
712 }
713 return null;
714 }
715 };
716 verifyRead(getAction);
717
718
719 AccessTestAction scanAction = new AccessTestAction() {
720 @Override
721 public Object run() throws Exception {
722 Scan s = new Scan();
723 s.addFamily(TEST_FAMILY);
724
725 HTable table = new HTable(conf, TEST_TABLE.getTableName());
726 try {
727 ResultScanner scanner = table.getScanner(s);
728 try {
729 for (Result r = scanner.next(); r != null; r = scanner.next()) {
730
731 }
732 } catch (IOException e) {
733 } finally {
734 scanner.close();
735 }
736 } finally {
737 table.close();
738 }
739 return null;
740 }
741 };
742 verifyRead(scanAction);
743 }
744
745 @Test
746
747 public void testWrite() throws Exception {
748
749 AccessTestAction putAction = new AccessTestAction() {
750 @Override
751 public Object run() throws Exception {
752 Put p = new Put(TEST_ROW);
753 p.add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1));
754 HTable t = new HTable(conf, TEST_TABLE.getTableName());
755 try {
756 t.put(p);
757 } finally {
758 t.close();
759 }
760 return null;
761 }
762 };
763 verifyWrite(putAction);
764
765
766 AccessTestAction deleteAction = new AccessTestAction() {
767 @Override
768 public Object run() throws Exception {
769 Delete d = new Delete(TEST_ROW);
770 d.deleteFamily(TEST_FAMILY);
771 HTable t = new HTable(conf, TEST_TABLE.getTableName());
772 try {
773 t.delete(d);
774 } finally {
775 t.close();
776 }
777 return null;
778 }
779 };
780 verifyWrite(deleteAction);
781
782
783 AccessTestAction incrementAction = new AccessTestAction() {
784 @Override
785 public Object run() throws Exception {
786 Increment inc = new Increment(TEST_ROW);
787 inc.addColumn(TEST_FAMILY, TEST_QUALIFIER, 1);
788 HTable t = new HTable(conf, TEST_TABLE.getTableName());
789 try {
790 t.increment(inc);
791 } finally {
792 t.close();
793 }
794 return null;
795 }
796 };
797 verifyWrite(incrementAction);
798 }
799
800 @Test
801 public void testReadWrite() throws Exception {
802
803 AccessTestAction checkAndDeleteAction = new AccessTestAction() {
804 @Override
805 public Object run() throws Exception {
806 Delete d = new Delete(TEST_ROW);
807 d.deleteFamily(TEST_FAMILY);
808 HTable t = new HTable(conf, TEST_TABLE.getTableName());
809 try {
810 t.checkAndDelete(TEST_ROW, TEST_FAMILY, TEST_QUALIFIER,
811 Bytes.toBytes("test_value"), d);
812 } finally {
813 t.close();
814 }
815 return null;
816 }
817 };
818 verifyReadWrite(checkAndDeleteAction);
819
820
821 AccessTestAction checkAndPut = new AccessTestAction() {
822 @Override
823 public Object run() throws Exception {
824 Put p = new Put(TEST_ROW);
825 p.add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1));
826 HTable t = new HTable(conf, TEST_TABLE.getTableName());
827 try {
828 t.checkAndPut(TEST_ROW, TEST_FAMILY, TEST_QUALIFIER,
829 Bytes.toBytes("test_value"), p);
830 } finally {
831 t.close();
832 }
833 return null;
834 }
835 };
836 verifyReadWrite(checkAndPut);
837 }
838
839 @Test
840 public void testBulkLoad() throws Exception {
841 FileSystem fs = TEST_UTIL.getTestFileSystem();
842 final Path dir = TEST_UTIL.getDataTestDirOnTestFS("testBulkLoad");
843 fs.mkdirs(dir);
844
845
846 fs.setPermission(dir, FsPermission.valueOf("-rwxrwxrwx"));
847
848 AccessTestAction bulkLoadAction = new AccessTestAction() {
849 @Override
850 public Object run() throws Exception {
851 int numRows = 3;
852
853
854 byte[][][] hfileRanges = {{{(byte)0}, {(byte)9}}};
855
856 Path bulkLoadBasePath = new Path(dir, new Path(User.getCurrent().getName()));
857 new BulkLoadHelper(bulkLoadBasePath)
858 .bulkLoadHFile(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_QUALIFIER, hfileRanges, numRows);
859
860 return null;
861 }
862 };
863
864
865
866 verifyAllowed(bulkLoadAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
867 verifyDenied(bulkLoadAction, USER_RW, USER_NONE, USER_RO);
868
869
870 TEST_UTIL.getHBaseAdmin().disableTable(TEST_TABLE.getTableName());
871 TEST_UTIL.getHBaseAdmin().enableTable(TEST_TABLE.getTableName());
872 }
873
874 public class BulkLoadHelper {
875 private final FileSystem fs;
876 private final Path loadPath;
877 private final Configuration conf;
878
879 public BulkLoadHelper(Path loadPath) throws IOException {
880 fs = TEST_UTIL.getTestFileSystem();
881 conf = TEST_UTIL.getConfiguration();
882 loadPath = loadPath.makeQualified(fs);
883 this.loadPath = loadPath;
884 }
885
886 private void createHFile(Path path,
887 byte[] family, byte[] qualifier,
888 byte[] startKey, byte[] endKey, int numRows) throws IOException {
889
890 HFile.Writer writer = null;
891 long now = System.currentTimeMillis();
892 try {
893 HFileContext context = new HFileContextBuilder().build();
894 writer = HFile.getWriterFactory(conf, new CacheConfig(conf))
895 .withPath(fs, path)
896 .withFileContext(context)
897 .create();
898
899 for (byte[] key : Bytes.iterateOnSplits(startKey, endKey, true, numRows-2)) {
900 KeyValue kv = new KeyValue(key, family, qualifier, now, key);
901 writer.append(kv);
902 }
903 } finally {
904 if(writer != null)
905 writer.close();
906 }
907 }
908
909 private void bulkLoadHFile(
910 TableName tableName,
911 byte[] family,
912 byte[] qualifier,
913 byte[][][] hfileRanges,
914 int numRowsPerRange) throws Exception {
915
916 Path familyDir = new Path(loadPath, Bytes.toString(family));
917 fs.mkdirs(familyDir);
918 int hfileIdx = 0;
919 for (byte[][] range : hfileRanges) {
920 byte[] from = range[0];
921 byte[] to = range[1];
922 createHFile(new Path(familyDir, "hfile_"+(hfileIdx++)),
923 family, qualifier, from, to, numRowsPerRange);
924 }
925
926 setPermission(loadPath, FsPermission.valueOf("-rwxrwxrwx"));
927
928 HTable table = new HTable(conf, tableName);
929 try {
930 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
931 TEST_UTIL.waitTableEnabled(admin, tableName.getName());
932 LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf);
933 loader.doBulkLoad(loadPath, table);
934 } finally {
935 table.close();
936 }
937 }
938
939 public void setPermission(Path dir, FsPermission perm) throws IOException {
940 if(!fs.getFileStatus(dir).isDir()) {
941 fs.setPermission(dir,perm);
942 }
943 else {
944 for(FileStatus el : fs.listStatus(dir)) {
945 fs.setPermission(el.getPath(), perm);
946 setPermission(el.getPath() , perm);
947 }
948 }
949 }
950 }
951
952 @Test
953 public void testAppend() throws Exception {
954
955 AccessTestAction appendAction = new AccessTestAction() {
956 @Override
957 public Object run() throws Exception {
958 byte[] row = TEST_ROW;
959 byte[] qualifier = TEST_QUALIFIER;
960 Put put = new Put(row);
961 put.add(TEST_FAMILY, qualifier, Bytes.toBytes(1));
962 Append append = new Append(row);
963 append.add(TEST_FAMILY, qualifier, Bytes.toBytes(2));
964 HTable t = new HTable(conf, TEST_TABLE.getTableName());
965 try {
966 t.put(put);
967 t.append(append);
968 } finally {
969 t.close();
970 }
971 return null;
972 }
973 };
974
975 verifyAllowed(appendAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW);
976 verifyDenied(appendAction, USER_RO, USER_NONE);
977 }
978
979 @Test
980 public void testGrantRevoke() throws Exception {
981 AccessTestAction grantAction = new AccessTestAction() {
982 @Override
983 public Object run() throws Exception {
984 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
985 try {
986 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
987 AccessControlService.BlockingInterface protocol =
988 AccessControlService.newBlockingStub(service);
989 ProtobufUtil.grant(protocol, USER_RO.getShortName(), TEST_TABLE.getTableName(),
990 TEST_FAMILY, null, Action.READ);
991 } finally {
992 acl.close();
993 }
994 return null;
995 }
996 };
997
998 AccessTestAction revokeAction = new AccessTestAction() {
999 @Override
1000 public Object run() throws Exception {
1001 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1002 try {
1003 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
1004 AccessControlService.BlockingInterface protocol =
1005 AccessControlService.newBlockingStub(service);
1006 ProtobufUtil.revoke(protocol, USER_RO.getShortName(), TEST_TABLE.getTableName(),
1007 TEST_FAMILY, null, Action.READ);
1008 } finally {
1009 acl.close();
1010 }
1011 return null;
1012 }
1013 };
1014
1015 AccessTestAction getTablePermissionsAction = new AccessTestAction() {
1016 @Override
1017 public Object run() throws Exception {
1018 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1019 try {
1020 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getTableName().getName());
1021 AccessControlService.BlockingInterface protocol =
1022 AccessControlService.newBlockingStub(service);
1023 ProtobufUtil.getUserPermissions(protocol, TEST_TABLE.getTableName());
1024 } finally {
1025 acl.close();
1026 }
1027 return null;
1028 }
1029 };
1030
1031 AccessTestAction getGlobalPermissionsAction = new AccessTestAction() {
1032 @Override
1033 public Object run() throws Exception {
1034 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1035 try {
1036 BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
1037 AccessControlService.BlockingInterface protocol =
1038 AccessControlService.newBlockingStub(service);
1039 ProtobufUtil.getUserPermissions(protocol);
1040 } finally {
1041 acl.close();
1042 }
1043 return null;
1044 }
1045 };
1046
1047 verifyAllowed(grantAction, SUPERUSER, USER_ADMIN, USER_OWNER);
1048 verifyDenied(grantAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
1049
1050 verifyAllowed(revokeAction, SUPERUSER, USER_ADMIN, USER_OWNER);
1051 verifyDenied(revokeAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
1052
1053 verifyAllowed(getTablePermissionsAction, SUPERUSER, USER_ADMIN, USER_OWNER);
1054 verifyDenied(getTablePermissionsAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
1055
1056 verifyAllowed(getGlobalPermissionsAction, SUPERUSER, USER_ADMIN);
1057 verifyDeniedWithException(getGlobalPermissionsAction, USER_CREATE,
1058 USER_OWNER, USER_RW, USER_RO, USER_NONE);
1059 }
1060
1061 @Test
1062 public void testPostGrantRevoke() throws Exception {
1063 final TableName tableName =
1064 TableName.valueOf("TempTable");
1065 final byte[] family1 = Bytes.toBytes("f1");
1066 final byte[] family2 = Bytes.toBytes("f2");
1067 final byte[] qualifier = Bytes.toBytes("q");
1068
1069
1070 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
1071 if (admin.tableExists(tableName)) {
1072 admin.disableTable(tableName);
1073 admin.deleteTable(tableName);
1074 }
1075 HTableDescriptor htd = new HTableDescriptor(tableName);
1076 htd.addFamily(new HColumnDescriptor(family1));
1077 htd.addFamily(new HColumnDescriptor(family2));
1078 admin.createTable(htd);
1079 TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
1080
1081
1082 User tblUser = User
1083 .createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser", new String[0]);
1084 User gblUser = User
1085 .createUserForTesting(TEST_UTIL.getConfiguration(), "gbluser", new String[0]);
1086
1087
1088 AccessTestAction putActionAll = new AccessTestAction() {
1089 @Override
1090 public Object run() throws Exception {
1091 Put p = new Put(Bytes.toBytes("a"));
1092 p.add(family1, qualifier, Bytes.toBytes("v1"));
1093 p.add(family2, qualifier, Bytes.toBytes("v2"));
1094 HTable t = new HTable(conf, tableName);
1095 try {
1096 t.put(p);
1097 } finally {
1098 t.close();
1099 }
1100 return null;
1101 }
1102 };
1103
1104 AccessTestAction putAction1 = new AccessTestAction() {
1105 @Override
1106 public Object run() throws Exception {
1107 Put p = new Put(Bytes.toBytes("a"));
1108 p.add(family1, qualifier, Bytes.toBytes("v1"));
1109 HTable t = new HTable(conf, tableName);
1110 try {
1111 t.put(p);
1112 } finally {
1113 t.close();
1114 }
1115 return null;
1116 }
1117 };
1118
1119 AccessTestAction putAction2 = new AccessTestAction() {
1120 @Override
1121 public Object run() throws Exception {
1122 Put p = new Put(Bytes.toBytes("a"));
1123 p.add(family2, qualifier, Bytes.toBytes("v2"));
1124 HTable t = new HTable(conf, tableName);
1125 try {
1126 t.put(p);
1127 } finally {
1128 t.close();
1129 }
1130 return null;
1131 }
1132 };
1133
1134 AccessTestAction getActionAll = new AccessTestAction() {
1135 @Override
1136 public Object run() throws Exception {
1137 Get g = new Get(TEST_ROW);
1138 g.addFamily(family1);
1139 g.addFamily(family2);
1140 HTable t = new HTable(conf, tableName);
1141 try {
1142 t.get(g);
1143 } finally {
1144 t.close();
1145 }
1146 return null;
1147 }
1148 };
1149
1150 AccessTestAction getAction1 = new AccessTestAction() {
1151 @Override
1152 public Object run() throws Exception {
1153 Get g = new Get(TEST_ROW);
1154 g.addFamily(family1);
1155 HTable t = new HTable(conf, tableName);
1156 try {
1157 t.get(g);
1158 } finally {
1159 t.close();
1160 }
1161 return null;
1162 }
1163 };
1164
1165 AccessTestAction getAction2 = new AccessTestAction() {
1166 @Override
1167 public Object run() throws Exception {
1168 Get g = new Get(TEST_ROW);
1169 g.addFamily(family2);
1170 HTable t = new HTable(conf, tableName);
1171 try {
1172 t.get(g);
1173 } finally {
1174 t.close();
1175 }
1176 return null;
1177 }
1178 };
1179
1180 AccessTestAction deleteActionAll = new AccessTestAction() {
1181 @Override
1182 public Object run() throws Exception {
1183 Delete d = new Delete(TEST_ROW);
1184 d.deleteFamily(family1);
1185 d.deleteFamily(family2);
1186 HTable t = new HTable(conf, tableName);
1187 try {
1188 t.delete(d);
1189 } finally {
1190 t.close();
1191 }
1192 return null;
1193 }
1194 };
1195
1196 AccessTestAction deleteAction1 = new AccessTestAction() {
1197 @Override
1198 public Object run() throws Exception {
1199 Delete d = new Delete(TEST_ROW);
1200 d.deleteFamily(family1);
1201 HTable t = new HTable(conf, tableName);
1202 try {
1203 t.delete(d);
1204 } finally {
1205 t.close();
1206 }
1207 return null;
1208 }
1209 };
1210
1211 AccessTestAction deleteAction2 = new AccessTestAction() {
1212 @Override
1213 public Object run() throws Exception {
1214 Delete d = new Delete(TEST_ROW);
1215 d.deleteFamily(family2);
1216 HTable t = new HTable(conf, tableName);
1217 try {
1218 t.delete(d);
1219 } finally {
1220 t.close();
1221 }
1222 return null;
1223 }
1224 };
1225
1226
1227 verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1228 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1229 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1230
1231 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1232 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1233 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1234
1235
1236 grantGlobal(TEST_UTIL, gblUser.getShortName(),
1237 Permission.Action.READ);
1238 grantOnTable(TEST_UTIL, tblUser.getShortName(),
1239 tableName, null, null,
1240 Permission.Action.READ);
1241
1242
1243 verifyAllowed(tblUser, getActionAll, getAction1, getAction2);
1244 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1245 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1246
1247 verifyAllowed(gblUser, getActionAll, getAction1, getAction2);
1248 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1249 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1250
1251
1252 grantGlobal(TEST_UTIL, gblUser.getShortName(),
1253 Permission.Action.WRITE);
1254 grantOnTable(TEST_UTIL, tblUser.getShortName(),
1255 tableName, null, null,
1256 Permission.Action.WRITE);
1257
1258 verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1259 verifyAllowed(tblUser, putActionAll, putAction1, putAction2);
1260 verifyAllowed(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1261
1262 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1263 verifyAllowed(gblUser, putActionAll, putAction1, putAction2);
1264 verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1265
1266
1267 revokeGlobal(TEST_UTIL, gblUser.getShortName());
1268 revokeFromTable(TEST_UTIL, tblUser.getShortName(),
1269 tableName, null, null);
1270
1271 verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1272 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1273 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1274
1275 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1276 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1277 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1278
1279
1280 grantGlobal(TEST_UTIL, gblUser.getShortName(),
1281 Permission.Action.READ);
1282 grantOnTable(TEST_UTIL, tblUser.getShortName(),
1283 tableName, family1, null, Permission.Action.READ);
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 verifyAllowed(gblUser, getActionAll, getAction1, getAction2);
1292 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1293 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1294
1295
1296 grantGlobal(TEST_UTIL, gblUser.getShortName(),
1297 Permission.Action.WRITE);
1298 grantOnTable(TEST_UTIL, tblUser.getShortName(),
1299 tableName, family2, null, Permission.Action.WRITE);
1300
1301
1302 verifyAllowed(tblUser, getActionAll, getAction1);
1303 verifyAllowed(tblUser, putAction2, deleteAction2);
1304 verifyDenied(tblUser, getAction2);
1305 verifyDenied(tblUser, putActionAll, putAction1);
1306 verifyDenied(tblUser, deleteActionAll, deleteAction1);
1307
1308 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1309 verifyAllowed(gblUser, putActionAll, putAction1, putAction2);
1310 verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1311
1312
1313 revokeGlobal(TEST_UTIL, gblUser.getShortName());
1314 revokeFromTable(TEST_UTIL, tblUser.getShortName(), tableName, family2, null);
1315
1316
1317 verifyAllowed(tblUser, getActionAll, getAction1);
1318 verifyDenied(tblUser, getAction2);
1319 verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1320 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1321
1322
1323 verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1324 verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1325 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1326
1327
1328 admin.disableTable(tableName);
1329 admin.deleteTable(tableName);
1330 }
1331
1332 private boolean hasFoundUserPermission(UserPermission userPermission, List<UserPermission> perms) {
1333 return perms.contains(userPermission);
1334 }
1335
1336 @Test
1337 public void testPostGrantRevokeAtQualifierLevel() throws Exception {
1338 final TableName tableName =
1339 TableName.valueOf("testGrantRevokeAtQualifierLevel");
1340 final byte[] family1 = Bytes.toBytes("f1");
1341 final byte[] family2 = Bytes.toBytes("f2");
1342 final byte[] qualifier = Bytes.toBytes("q");
1343
1344
1345 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
1346 if (admin.tableExists(tableName)) {
1347 admin.disableTable(tableName);
1348 admin.deleteTable(tableName);
1349 }
1350 HTableDescriptor htd = new HTableDescriptor(tableName);
1351 htd.addFamily(new HColumnDescriptor(family1));
1352 htd.addFamily(new HColumnDescriptor(family2));
1353 admin.createTable(htd);
1354 TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
1355
1356
1357 User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]);
1358
1359 AccessTestAction getQualifierAction = new AccessTestAction() {
1360 @Override
1361 public Object run() throws Exception {
1362 Get g = new Get(TEST_ROW);
1363 g.addColumn(family1, qualifier);
1364 HTable t = new HTable(conf, tableName);
1365 try {
1366 t.get(g);
1367 } finally {
1368 t.close();
1369 }
1370 return null;
1371 }
1372 };
1373
1374 AccessTestAction putQualifierAction = new AccessTestAction() {
1375 @Override
1376 public Object run() throws Exception {
1377 Put p = new Put(TEST_ROW);
1378 p.add(family1, qualifier, Bytes.toBytes("v1"));
1379 HTable t = new HTable(conf, tableName);
1380 try {
1381 t.put(p);
1382 } finally {
1383 t.close();
1384 }
1385 return null;
1386 }
1387 };
1388
1389 AccessTestAction deleteQualifierAction = new AccessTestAction() {
1390 @Override
1391 public Object run() throws Exception {
1392 Delete d = new Delete(TEST_ROW);
1393 d.deleteColumn(family1, qualifier);
1394
1395 HTable t = new HTable(conf, tableName);
1396 try {
1397 t.delete(d);
1398 } finally {
1399 t.close();
1400 }
1401 return null;
1402 }
1403 };
1404
1405 revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, null);
1406
1407 verifyDenied(user, getQualifierAction);
1408 verifyDenied(user, putQualifierAction);
1409 verifyDenied(user, deleteQualifierAction);
1410
1411 grantOnTable(TEST_UTIL, user.getShortName(),
1412 tableName, family1, qualifier,
1413 Permission.Action.READ);
1414
1415 verifyAllowed(user, getQualifierAction);
1416 verifyDenied(user, putQualifierAction);
1417 verifyDenied(user, deleteQualifierAction);
1418
1419
1420
1421 grantOnTable(TEST_UTIL, user.getShortName(),
1422 tableName, family1, qualifier,
1423 Permission.Action.WRITE);
1424
1425 verifyDenied(user, getQualifierAction);
1426 verifyAllowed(user, putQualifierAction);
1427 verifyAllowed(user, deleteQualifierAction);
1428
1429
1430 grantOnTable(TEST_UTIL, user.getShortName(),
1431 tableName, family1, qualifier,
1432 Permission.Action.READ, Permission.Action.WRITE);
1433
1434 verifyAllowed(user, getQualifierAction);
1435 verifyAllowed(user, putQualifierAction);
1436 verifyAllowed(user, deleteQualifierAction);
1437
1438
1439 revokeFromTable(TEST_UTIL, user.getShortName(),
1440 tableName, family1, qualifier);
1441
1442 verifyDenied(user, getQualifierAction);
1443 verifyDenied(user, putQualifierAction);
1444 verifyDenied(user, deleteQualifierAction);
1445
1446
1447 admin.disableTable(tableName);
1448 admin.deleteTable(tableName);
1449 }
1450
1451 @Test
1452 public void testPermissionList() throws Exception {
1453 final TableName tableName =
1454 TableName.valueOf("testPermissionList");
1455 final byte[] family1 = Bytes.toBytes("f1");
1456 final byte[] family2 = Bytes.toBytes("f2");
1457 final byte[] qualifier = Bytes.toBytes("q");
1458
1459
1460 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
1461 if (admin.tableExists(tableName)) {
1462 admin.disableTable(tableName);
1463 admin.deleteTable(tableName);
1464 }
1465 HTableDescriptor htd = new HTableDescriptor(tableName);
1466 htd.addFamily(new HColumnDescriptor(family1));
1467 htd.addFamily(new HColumnDescriptor(family2));
1468 htd.setOwner(USER_OWNER);
1469 admin.createTable(htd);
1470 TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
1471
1472 List<UserPermission> perms;
1473
1474 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1475 try {
1476 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1477 AccessControlService.BlockingInterface protocol =
1478 AccessControlService.newBlockingStub(service);
1479 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1480 } finally {
1481 acl.close();
1482 }
1483
1484 UserPermission ownerperm = new UserPermission(
1485 Bytes.toBytes(USER_OWNER.getName()), tableName, null, Action.values());
1486 assertTrue("Owner should have all permissions on table",
1487 hasFoundUserPermission(ownerperm, perms));
1488
1489 User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]);
1490 byte[] userName = Bytes.toBytes(user.getShortName());
1491
1492 UserPermission up = new UserPermission(userName,
1493 tableName, family1, qualifier, Permission.Action.READ);
1494 assertFalse("User should not be granted permission: " + up.toString(),
1495 hasFoundUserPermission(up, perms));
1496
1497
1498 grantOnTable(TEST_UTIL, user.getShortName(),
1499 tableName, family1, qualifier, Permission.Action.READ);
1500
1501 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1502 try {
1503 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1504 AccessControlService.BlockingInterface protocol =
1505 AccessControlService.newBlockingStub(service);
1506 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1507 } finally {
1508 acl.close();
1509 }
1510
1511 UserPermission upToVerify = new UserPermission(
1512 userName, tableName, family1, qualifier, Permission.Action.READ);
1513 assertTrue("User should be granted permission: " + upToVerify.toString(),
1514 hasFoundUserPermission(upToVerify, perms));
1515
1516 upToVerify = new UserPermission(
1517 userName, tableName, family1, qualifier, Permission.Action.WRITE);
1518 assertFalse("User should not be granted permission: " + upToVerify.toString(),
1519 hasFoundUserPermission(upToVerify, perms));
1520
1521
1522 grantOnTable(TEST_UTIL, user.getShortName(),
1523 tableName, family1, qualifier,
1524 Permission.Action.WRITE, Permission.Action.READ);
1525
1526 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1527 try {
1528 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1529 AccessControlService.BlockingInterface protocol =
1530 AccessControlService.newBlockingStub(service);
1531 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1532 } finally {
1533 acl.close();
1534 }
1535
1536 upToVerify = new UserPermission(userName, tableName, family1,
1537 qualifier, Permission.Action.WRITE, Permission.Action.READ);
1538 assertTrue("User should be granted permission: " + upToVerify.toString(),
1539 hasFoundUserPermission(upToVerify, perms));
1540
1541
1542 revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
1543 Permission.Action.WRITE, Permission.Action.READ);
1544
1545 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1546 try {
1547 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1548 AccessControlService.BlockingInterface protocol =
1549 AccessControlService.newBlockingStub(service);
1550 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1551 } finally {
1552 acl.close();
1553 }
1554
1555 assertFalse("User should not be granted permission: " + upToVerify.toString(),
1556 hasFoundUserPermission(upToVerify, perms));
1557
1558
1559 admin.disableTable(tableName);
1560
1561 User newOwner = User.createUserForTesting(conf, "new_owner", new String[] {});
1562 htd.setOwner(newOwner);
1563 admin.modifyTable(tableName, htd);
1564
1565 acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1566 try {
1567 BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1568 AccessControlService.BlockingInterface protocol =
1569 AccessControlService.newBlockingStub(service);
1570 perms = ProtobufUtil.getUserPermissions(protocol, tableName);
1571 } finally {
1572 acl.close();
1573 }
1574
1575 UserPermission newOwnerperm = new UserPermission(
1576 Bytes.toBytes(newOwner.getName()), tableName, null, Action.values());
1577 assertTrue("New owner should have all permissions on table",
1578 hasFoundUserPermission(newOwnerperm, perms));
1579
1580
1581 admin.deleteTable(tableName);
1582 }
1583
1584 @Test
1585 public void testGlobalPermissionList() throws Exception {
1586 List<UserPermission> perms;
1587 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1588 try {
1589 BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
1590 AccessControlService.BlockingInterface protocol =
1591 AccessControlService.newBlockingStub(service);
1592 perms = ProtobufUtil.getUserPermissions(protocol);
1593 } finally {
1594 acl.close();
1595 }
1596 UserPermission adminPerm = new UserPermission(Bytes.toBytes(USER_ADMIN.getShortName()),
1597 AccessControlLists.ACL_TABLE_NAME, null, null, Bytes.toBytes("ACRW"));
1598 assertTrue("Only user admin has permission on table _acl_ per setup",
1599 perms.size() == 1 && hasFoundUserPermission(adminPerm, perms));
1600 }
1601
1602
1603 private void verifyGlobal(AccessTestAction action) throws Exception {
1604 verifyAllowed(action, SUPERUSER);
1605
1606 verifyDenied(action, USER_CREATE, USER_RW, USER_NONE, USER_RO);
1607 }
1608
1609 public void checkGlobalPerms(Permission.Action... actions) throws IOException {
1610 Permission[] perms = new Permission[actions.length];
1611 for (int i = 0; i < actions.length; i++) {
1612 perms[i] = new Permission(actions[i]);
1613 }
1614 CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
1615 for (Action a : actions) {
1616 request.addPermission(AccessControlProtos.Permission.newBuilder()
1617 .setType(AccessControlProtos.Permission.Type.Global)
1618 .setGlobalPermission(
1619 AccessControlProtos.GlobalPermission.newBuilder()
1620 .addAction(ProtobufUtil.toPermissionAction(a)).build()));
1621 }
1622 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1623 try {
1624 BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
1625 AccessControlService.BlockingInterface protocol =
1626 AccessControlService.newBlockingStub(channel);
1627 try {
1628 protocol.checkPermissions(null, request.build());
1629 } catch (ServiceException se) {
1630 ProtobufUtil.toIOException(se);
1631 }
1632 } finally {
1633 acl.close();
1634 }
1635 }
1636
1637 public void checkTablePerms(TableName table, byte[] family, byte[] column,
1638 Permission.Action... actions) throws IOException {
1639 Permission[] perms = new Permission[actions.length];
1640 for (int i = 0; i < actions.length; i++) {
1641 perms[i] = new TablePermission(table, family, column, actions[i]);
1642 }
1643
1644 checkTablePerms(table, perms);
1645 }
1646
1647 public void checkTablePerms(TableName table, Permission... perms) throws IOException {
1648 CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
1649 for (Permission p : perms) {
1650 request.addPermission(ProtobufUtil.toPermission(p));
1651 }
1652 HTable acl = new HTable(conf, table);
1653 try {
1654 AccessControlService.BlockingInterface protocol =
1655 AccessControlService.newBlockingStub(acl.coprocessorService(new byte[0]));
1656 try {
1657 protocol.checkPermissions(null, request.build());
1658 } catch (ServiceException se) {
1659 ProtobufUtil.toIOException(se);
1660 }
1661 } finally {
1662 acl.close();
1663 }
1664 }
1665
1666 @Test
1667 public void testCheckPermissions() throws Exception {
1668
1669
1670 AccessTestAction globalAdmin = new AccessTestAction() {
1671 @Override
1672 public Void run() throws Exception {
1673 checkGlobalPerms(Permission.Action.ADMIN);
1674 return null;
1675 }
1676 };
1677
1678 verifyGlobal(globalAdmin);
1679
1680
1681
1682 AccessTestAction globalReadWrite = new AccessTestAction() {
1683 @Override
1684 public Void run() throws Exception {
1685 checkGlobalPerms(Permission.Action.READ, Permission.Action.WRITE);
1686 return null;
1687 }
1688 };
1689
1690 verifyGlobal(globalReadWrite);
1691
1692
1693
1694 final byte[] TEST_Q1 = Bytes.toBytes("q1");
1695 final byte[] TEST_Q2 = Bytes.toBytes("q2");
1696
1697 User userTable = User.createUserForTesting(conf, "user_check_perms_table", new String[0]);
1698 User userColumn = User.createUserForTesting(conf, "user_check_perms_family", new String[0]);
1699 User userQualifier = User.createUserForTesting(conf, "user_check_perms_q", new String[0]);
1700
1701 grantOnTable(TEST_UTIL, userTable.getShortName(),
1702 TEST_TABLE.getTableName(), null, null,
1703 Permission.Action.READ);
1704 grantOnTable(TEST_UTIL, userColumn.getShortName(),
1705 TEST_TABLE.getTableName(), TEST_FAMILY, null,
1706 Permission.Action.READ);
1707 grantOnTable(TEST_UTIL, userQualifier.getShortName(),
1708 TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
1709 Permission.Action.READ);
1710
1711 AccessTestAction tableRead = new AccessTestAction() {
1712 @Override
1713 public Void run() throws Exception {
1714 checkTablePerms(TEST_TABLE.getTableName(), null, null, Permission.Action.READ);
1715 return null;
1716 }
1717 };
1718
1719 AccessTestAction columnRead = new AccessTestAction() {
1720 @Override
1721 public Void run() throws Exception {
1722 checkTablePerms(TEST_TABLE.getTableName(), TEST_FAMILY, null, Permission.Action.READ);
1723 return null;
1724 }
1725 };
1726
1727 AccessTestAction qualifierRead = new AccessTestAction() {
1728 @Override
1729 public Void run() throws Exception {
1730 checkTablePerms(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1, Permission.Action.READ);
1731 return null;
1732 }
1733 };
1734
1735 AccessTestAction multiQualifierRead = new AccessTestAction() {
1736 @Override
1737 public Void run() throws Exception {
1738 checkTablePerms(TEST_TABLE.getTableName(), new Permission[] {
1739 new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1, Permission.Action.READ),
1740 new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q2, Permission.Action.READ), });
1741 return null;
1742 }
1743 };
1744
1745 AccessTestAction globalAndTableRead = new AccessTestAction() {
1746 @Override
1747 public Void run() throws Exception {
1748 checkTablePerms(TEST_TABLE.getTableName(), new Permission[] { new Permission(Permission.Action.READ),
1749 new TablePermission(TEST_TABLE.getTableName(), null, (byte[]) null, Permission.Action.READ), });
1750 return null;
1751 }
1752 };
1753
1754 AccessTestAction noCheck = new AccessTestAction() {
1755 @Override
1756 public Void run() throws Exception {
1757 checkTablePerms(TEST_TABLE.getTableName(), new Permission[0]);
1758 return null;
1759 }
1760 };
1761
1762 verifyAllowed(tableRead, SUPERUSER, userTable);
1763 verifyDenied(tableRead, userColumn, userQualifier);
1764
1765 verifyAllowed(columnRead, SUPERUSER, userTable, userColumn);
1766 verifyDenied(columnRead, userQualifier);
1767
1768 verifyAllowed(qualifierRead, SUPERUSER, userTable, userColumn, userQualifier);
1769
1770 verifyAllowed(multiQualifierRead, SUPERUSER, userTable, userColumn);
1771 verifyDenied(multiQualifierRead, userQualifier);
1772
1773 verifyAllowed(globalAndTableRead, SUPERUSER);
1774 verifyDenied(globalAndTableRead, userTable, userColumn, userQualifier);
1775
1776 verifyAllowed(noCheck, SUPERUSER, userTable, userColumn, userQualifier);
1777
1778
1779
1780 AccessTestAction familyReadWrite = new AccessTestAction() {
1781 @Override
1782 public Void run() throws Exception {
1783 checkTablePerms(TEST_TABLE.getTableName(), TEST_FAMILY, null, Permission.Action.READ,
1784 Permission.Action.WRITE);
1785 return null;
1786 }
1787 };
1788
1789 verifyAllowed(familyReadWrite, SUPERUSER, USER_OWNER, USER_CREATE, USER_RW);
1790 verifyDenied(familyReadWrite, USER_NONE, USER_RO);
1791
1792
1793
1794 CheckPermissionsRequest checkRequest = CheckPermissionsRequest.newBuilder()
1795 .addPermission(AccessControlProtos.Permission.newBuilder()
1796 .setType(AccessControlProtos.Permission.Type.Table)
1797 .setTablePermission(
1798 AccessControlProtos.TablePermission.newBuilder()
1799 .setTableName(ProtobufUtil.toProtoTableName(TEST_TABLE.getTableName()))
1800 .addAction(AccessControlProtos.Permission.Action.CREATE))
1801 ).build();
1802 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
1803 try {
1804 BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
1805 AccessControlService.BlockingInterface protocol =
1806 AccessControlService.newBlockingStub(channel);
1807 try {
1808
1809 protocol.checkPermissions(null, checkRequest);
1810 fail("this should have thrown CoprocessorException");
1811 } catch (ServiceException ex) {
1812
1813 }
1814 } finally {
1815 acl.close();
1816 }
1817 }
1818
1819 @Test
1820 public void testStopRegionServer() throws Exception {
1821 AccessTestAction action = new AccessTestAction() {
1822 @Override
1823 public Object run() throws Exception {
1824 ACCESS_CONTROLLER.preStopRegionServer(ObserverContext.createAndPrepare(RSCP_ENV, null));
1825 return null;
1826 }
1827 };
1828
1829 verifyAllowed(action, SUPERUSER, USER_ADMIN);
1830 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
1831 }
1832
1833 @Test
1834 public void testRollWALWriterRequest() throws Exception {
1835 AccessTestAction action = new AccessTestAction() {
1836 @Override
1837 public Object run() throws Exception {
1838 ACCESS_CONTROLLER.preRollWALWriterRequest(ObserverContext.createAndPrepare(RSCP_ENV, null));
1839 return null;
1840 }
1841 };
1842
1843 verifyAllowed(action, SUPERUSER, USER_ADMIN);
1844 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
1845 }
1846
1847 @Test
1848 public void testOpenRegion() throws Exception {
1849 AccessTestAction action = new AccessTestAction() {
1850 @Override
1851 public Object run() throws Exception {
1852 ACCESS_CONTROLLER.preOpen(ObserverContext.createAndPrepare(RCP_ENV, null));
1853 return null;
1854 }
1855 };
1856
1857 verifyAllowed(action, SUPERUSER, USER_ADMIN);
1858 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1859 }
1860
1861 @Test
1862 public void testCloseRegion() throws Exception {
1863 AccessTestAction action = new AccessTestAction() {
1864 @Override
1865 public Object run() throws Exception {
1866 ACCESS_CONTROLLER.preClose(ObserverContext.createAndPrepare(RCP_ENV, null), false);
1867 return null;
1868 }
1869 };
1870
1871 verifyAllowed(action, SUPERUSER, USER_ADMIN);
1872 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1873 }
1874
1875 @Test
1876 public void testSnapshot() throws Exception {
1877 AccessTestAction snapshotAction = new AccessTestAction() {
1878 @Override
1879 public Object run() throws Exception {
1880 ACCESS_CONTROLLER.preSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1881 null, null);
1882 return null;
1883 }
1884 };
1885
1886 AccessTestAction deleteAction = new AccessTestAction() {
1887 @Override
1888 public Object run() throws Exception {
1889 ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1890 null);
1891 return null;
1892 }
1893 };
1894
1895 AccessTestAction restoreAction = new AccessTestAction() {
1896 @Override
1897 public Object run() throws Exception {
1898 ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1899 null, null);
1900 return null;
1901 }
1902 };
1903
1904 AccessTestAction cloneAction = new AccessTestAction() {
1905 @Override
1906 public Object run() throws Exception {
1907 ACCESS_CONTROLLER.preCloneSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1908 null, null);
1909 return null;
1910 }
1911 };
1912
1913 verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN);
1914 verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1915
1916 verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN);
1917 verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1918
1919 verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN);
1920 verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1921
1922 verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN);
1923 verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
1924 }
1925
1926 @Test
1927 public void testGlobalAuthorizationForNewRegisteredRS() throws Exception {
1928 LOG.debug("Test for global authorization for a new registered RegionServer.");
1929 MiniHBaseCluster hbaseCluster = TEST_UTIL.getHBaseCluster();
1930
1931
1932
1933 String currentUser = User.getCurrent().getShortName();
1934 String activeUserForNewRs = currentUser + ".hfs." +
1935 hbaseCluster.getLiveRegionServerThreads().size();
1936 grantGlobal(TEST_UTIL, activeUserForNewRs,
1937 Permission.Action.ADMIN, Permission.Action.CREATE, Permission.Action.READ,
1938 Permission.Action.WRITE);
1939
1940 final HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
1941 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE2);
1942 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
1943 admin.createTable(htd);
1944 TEST_UTIL.waitUntilAllRegionsAssigned(TEST_TABLE2);
1945
1946
1947 JVMClusterUtil.RegionServerThread newRsThread = hbaseCluster
1948 .startRegionServer();
1949 final HRegionServer newRs = newRsThread.getRegionServer();
1950
1951
1952 final HTable table = new HTable(TEST_UTIL.getConfiguration(), TEST_TABLE2);
1953 try {
1954 NavigableMap<HRegionInfo, ServerName> regions = table
1955 .getRegionLocations();
1956 final Map.Entry<HRegionInfo, ServerName> firstRegion = regions.entrySet()
1957 .iterator().next();
1958
1959 AccessTestAction moveAction = new AccessTestAction() {
1960 @Override
1961 public Object run() throws Exception {
1962 admin.move(firstRegion.getKey().getEncodedNameAsBytes(),
1963 Bytes.toBytes(newRs.getServerName().getServerName()));
1964 return null;
1965 }
1966 };
1967 SUPERUSER.runAs(moveAction);
1968
1969 final int RETRIES_LIMIT = 10;
1970 int retries = 0;
1971 while (newRs.getOnlineRegions(TEST_TABLE2).size() < 1 && retries < RETRIES_LIMIT) {
1972 LOG.debug("Waiting for region to be opened. Already retried " + retries
1973 + " times.");
1974 try {
1975 Thread.sleep(1000);
1976 } catch (InterruptedException e) {
1977 }
1978 retries++;
1979 if (retries == RETRIES_LIMIT - 1) {
1980 fail("Retry exhaust for waiting region to be opened.");
1981 }
1982 }
1983
1984
1985 AccessTestAction putAction = new AccessTestAction() {
1986 @Override
1987 public Object run() throws Exception {
1988 Put put = new Put(Bytes.toBytes("test"));
1989 put.add(TEST_FAMILY, Bytes.toBytes("qual"), Bytes.toBytes("value"));
1990 table.put(put);
1991 return null;
1992 }
1993 };
1994 USER_ADMIN.runAs(putAction);
1995 } finally {
1996 table.close();
1997 }
1998 }
1999
2000 @Test
2001 public void testTableDescriptorsEnumeration() throws Exception {
2002 User TABLE_ADMIN = User.createUserForTesting(conf, "UserA", new String[0]);
2003
2004
2005 grantOnTable(TEST_UTIL, TABLE_ADMIN.getShortName(),
2006 TEST_TABLE.getTableName(), null, null,
2007 Permission.Action.ADMIN);
2008
2009 AccessTestAction listTablesAction = new AccessTestAction() {
2010 @Override
2011 public Object run() throws Exception {
2012 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
2013 try {
2014 admin.listTables();
2015 } finally {
2016 admin.close();
2017 }
2018 return null;
2019 }
2020 };
2021
2022 AccessTestAction getTableDescAction = new AccessTestAction() {
2023 @Override
2024 public Object run() throws Exception {
2025 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
2026 try {
2027 admin.getTableDescriptor(TEST_TABLE.getTableName());
2028 } finally {
2029 admin.close();
2030 }
2031 return null;
2032 }
2033 };
2034
2035 verifyAllowed(listTablesAction, SUPERUSER, USER_ADMIN);
2036 verifyDenied(listTablesAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, TABLE_ADMIN);
2037
2038 verifyAllowed(getTableDescAction, SUPERUSER, USER_ADMIN, USER_CREATE, TABLE_ADMIN);
2039 verifyDenied(getTableDescAction, USER_RW, USER_RO, USER_NONE);
2040 }
2041
2042 @Test
2043 public void testTableDeletion() throws Exception {
2044 User TABLE_ADMIN = User.createUserForTesting(conf, "TestUser", new String[0]);
2045
2046
2047 grantOnTable(TEST_UTIL, TABLE_ADMIN.getShortName(),
2048 TEST_TABLE.getTableName(), null, null,
2049 Permission.Action.ADMIN);
2050
2051 AccessTestAction deleteTableAction = new AccessTestAction() {
2052 @Override
2053 public Object run() throws Exception {
2054 HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
2055 try {
2056 admin.disableTable(TEST_TABLE.getTableName());
2057 admin.deleteTable(TEST_TABLE.getTableName());
2058 } finally {
2059 admin.close();
2060 }
2061 return null;
2062 }
2063 };
2064
2065 verifyDenied(deleteTableAction, USER_RW, USER_RO, USER_NONE);
2066 verifyAllowed(deleteTableAction, TABLE_ADMIN);
2067 }
2068
2069 @Test
2070 public void testNamespaceUserGrant() throws Exception {
2071 AccessTestAction getAction = new AccessTestAction() {
2072 @Override
2073 public Object run() throws Exception {
2074 HTable t = new HTable(conf, TEST_TABLE.getTableName());
2075 try {
2076 return t.get(new Get(TEST_ROW));
2077 } finally {
2078 t.close();
2079 }
2080 }
2081 };
2082
2083 verifyDenied(getAction, USER_NONE);
2084
2085
2086 grantOnNamespace(TEST_UTIL, USER_NONE.getShortName(),
2087 TEST_TABLE.getTableName().getNamespaceAsString(),
2088 Permission.Action.READ);
2089
2090
2091 verifyAllowed(getAction, USER_NONE);
2092 }
2093
2094 @Test
2095 public void testAccessControlClientGrantRevoke() throws Exception {
2096
2097 User testGrantRevoke = User.createUserForTesting(conf, "testGrantRevoke", new String[0]);
2098 AccessTestAction getAction = new AccessTestAction() {
2099 @Override
2100 public Object run() throws Exception {
2101 HTable t = new HTable(conf, TEST_TABLE.getTableName());
2102 try {
2103 return t.get(new Get(TEST_ROW));
2104 } finally {
2105 t.close();
2106 }
2107 }
2108 };
2109
2110 verifyDenied(getAction, testGrantRevoke);
2111
2112
2113 try {
2114 grantOnTableUsingAccessControlClient(TEST_UTIL, conf, testGrantRevoke.getShortName(),
2115 TEST_TABLE.getTableName(), null, null, Permission.Action.READ);
2116 } catch (Throwable e) {
2117 LOG.error("error during call of AccessControlClient.grant. " + e.getStackTrace());
2118 }
2119
2120
2121 verifyAllowed(getAction, testGrantRevoke);
2122
2123
2124 try {
2125 revokeFromTableUsingAccessControlClient(TEST_UTIL, conf, testGrantRevoke.getShortName(),
2126 TEST_TABLE.getTableName(), null, null, Permission.Action.READ);
2127 } catch (Throwable e) {
2128 LOG.error("error during call of AccessControlClient.revoke " + e.getStackTrace());
2129 }
2130
2131
2132 verifyDenied(getAction, testGrantRevoke);
2133 }
2134
2135 @Test
2136 public void testAccessControlClientGlobalGrantRevoke() throws Exception {
2137
2138 User testGlobalGrantRevoke = User.createUserForTesting(conf,
2139 "testGlobalGrantRevoke", new String[0]);
2140 AccessTestAction getAction = new AccessTestAction() {
2141 @Override
2142 public Object run() throws Exception {
2143 HTable t = new HTable(conf, TEST_TABLE.getTableName());
2144 try {
2145 return t.get(new Get(TEST_ROW));
2146 } finally {
2147 t.close();
2148 }
2149 }
2150 };
2151
2152 verifyDenied(getAction, testGlobalGrantRevoke);
2153
2154
2155 try {
2156 grantGlobalUsingAccessControlClient(TEST_UTIL, conf, testGlobalGrantRevoke.getShortName(),
2157 Permission.Action.READ);
2158 } catch (Throwable e) {
2159 LOG.error("error during call of AccessControlClient.grant. ", e);
2160 }
2161
2162
2163 verifyAllowed(getAction, testGlobalGrantRevoke);
2164
2165
2166 try {
2167 revokeGlobalUsingAccessControlClient(TEST_UTIL, conf, testGlobalGrantRevoke.getShortName(),
2168 Permission.Action.READ);
2169 } catch (Throwable e) {
2170 LOG.error("error during call of AccessControlClient.revoke ", e);
2171 }
2172
2173
2174 verifyDenied(getAction, testGlobalGrantRevoke);
2175 }
2176
2177 @Test
2178 public void testAccessControlClientGrantRevokeOnNamespace() throws Exception {
2179
2180 User testNS = User.createUserForTesting(conf, "testNS", new String[0]);
2181 AccessTestAction getAction = new AccessTestAction() {
2182 @Override
2183 public Object run() throws Exception {
2184 HTable t = new HTable(conf, TEST_TABLE.getTableName());
2185 try {
2186 return t.get(new Get(TEST_ROW));
2187 } finally {
2188 t.close();
2189 }
2190 }
2191 };
2192
2193 verifyDenied(getAction, testNS);
2194
2195
2196 try {
2197 grantOnNamespaceUsingAccessControlClient(TEST_UTIL, conf, testNS.getShortName(),
2198 TEST_TABLE.getTableName().getNamespaceAsString(), Permission.Action.READ);
2199 } catch (Throwable e) {
2200 LOG.error("error during call of AccessControlClient.grant. " + e.getStackTrace());
2201 }
2202
2203
2204 verifyAllowed(getAction, testNS);
2205
2206
2207 try {
2208 revokeFromNamespaceUsingAccessControlClient(TEST_UTIL, conf, testNS.getShortName(),
2209 TEST_TABLE.getTableName().getNamespaceAsString(), Permission.Action.READ);
2210 } catch (Throwable e) {
2211 LOG.error("error during call of AccessControlClient.revoke " + e.getStackTrace());
2212 }
2213
2214
2215 verifyDenied(getAction, testNS);
2216 }
2217
2218
2219 public static class PingCoprocessor extends PingService implements Coprocessor,
2220 CoprocessorService {
2221
2222 @Override
2223 public void start(CoprocessorEnvironment env) throws IOException { }
2224
2225 @Override
2226 public void stop(CoprocessorEnvironment env) throws IOException { }
2227
2228 @Override
2229 public Service getService() {
2230 return this;
2231 }
2232
2233 @Override
2234 public void ping(RpcController controller, PingRequest request,
2235 RpcCallback<PingResponse> callback) {
2236 callback.run(PingResponse.newBuilder().setPong("Pong!").build());
2237 }
2238
2239 @Override
2240 public void count(RpcController controller, CountRequest request,
2241 RpcCallback<CountResponse> callback) {
2242 callback.run(CountResponse.newBuilder().build());
2243 }
2244
2245 @Override
2246 public void increment(RpcController controller, IncrementCountRequest requet,
2247 RpcCallback<IncrementCountResponse> callback) {
2248 callback.run(IncrementCountResponse.newBuilder().build());
2249 }
2250
2251 @Override
2252 public void hello(RpcController controller, HelloRequest request,
2253 RpcCallback<HelloResponse> callback) {
2254 callback.run(HelloResponse.newBuilder().setResponse("Hello!").build());
2255 }
2256
2257 @Override
2258 public void noop(RpcController controller, NoopRequest request,
2259 RpcCallback<NoopResponse> callback) {
2260 callback.run(NoopResponse.newBuilder().build());
2261 }
2262 }
2263
2264 @Test
2265 public void testCoprocessorExec() throws Exception {
2266
2267 for (JVMClusterUtil.RegionServerThread thread:
2268 TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
2269 HRegionServer rs = thread.getRegionServer();
2270 for (HRegion region: rs.getOnlineRegions(TEST_TABLE.getTableName())) {
2271 region.getCoprocessorHost().load(PingCoprocessor.class,
2272 Coprocessor.PRIORITY_USER, conf);
2273 }
2274 }
2275
2276
2277
2278 User userA = User.createUserForTesting(conf, "UserA", new String[0]);
2279 User userB = User.createUserForTesting(conf, "UserB", new String[0]);
2280
2281 grantOnTable(TEST_UTIL, userA.getShortName(),
2282 TEST_TABLE.getTableName(), null, null,
2283 Permission.Action.EXEC);
2284
2285
2286 AccessTestAction execEndpointAction = new AccessTestAction() {
2287 @Override
2288 public Object run() throws Exception {
2289 HTable t = new HTable(conf, TEST_TABLE.getTableName());
2290 try {
2291 BlockingRpcChannel service = t.coprocessorService(HConstants.EMPTY_BYTE_ARRAY);
2292 PingCoprocessor.newBlockingStub(service).noop(null, NoopRequest.newBuilder().build());
2293 } finally {
2294 t.close();
2295 }
2296 return null;
2297 }
2298 };
2299
2300
2301 verifyDenied(execEndpointAction, userB);
2302 verifyAllowed(execEndpointAction, userA);
2303
2304
2305 grantOnNamespace(TEST_UTIL, userB.getShortName(),
2306 TEST_TABLE.getTableName().getNamespaceAsString(),
2307 Permission.Action.EXEC);
2308
2309
2310 verifyAllowed(execEndpointAction, userA, userB);
2311 }
2312
2313 @Test
2314 public void testReservedCellTags() throws Exception {
2315 AccessTestAction putWithReservedTag = new AccessTestAction() {
2316 @Override
2317 public Object run() throws Exception {
2318 HTable t = new HTable(conf, TEST_TABLE.getTableName());
2319 try {
2320 KeyValue kv = new KeyValue(TEST_ROW, TEST_FAMILY, TEST_QUALIFIER,
2321 HConstants.LATEST_TIMESTAMP, HConstants.EMPTY_BYTE_ARRAY,
2322 new Tag[] { new Tag(AccessControlLists.ACL_TAG_TYPE,
2323 ProtobufUtil.toUsersAndPermissions(USER_OWNER.getShortName(),
2324 new Permission(Permission.Action.READ)).toByteArray()) });
2325 t.put(new Put(TEST_ROW).add(kv));
2326 } finally {
2327 t.close();
2328 }
2329 return null;
2330 }
2331 };
2332
2333
2334 verifyAllowed(putWithReservedTag, User.getCurrent());
2335
2336 verifyDenied(putWithReservedTag, USER_OWNER, USER_ADMIN, USER_CREATE, USER_RW, USER_RO);
2337 }
2338
2339 @Test
2340 public void testGetNamespacePermission() throws Exception {
2341 String namespace = "testNamespace";
2342 NamespaceDescriptor desc = NamespaceDescriptor.create(namespace).build();
2343 TEST_UTIL.getMiniHBaseCluster().getMaster().createNamespace(desc);
2344 grantOnNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ);
2345 try {
2346 List<UserPermission> namespacePermissions = AccessControlClient.getUserPermissions(conf,
2347 AccessControlLists.toNamespaceEntry(namespace));
2348 assertTrue(namespacePermissions != null);
2349 assertTrue(namespacePermissions.size() == 1);
2350 } catch (Throwable thw) {
2351 throw new HBaseException(thw);
2352 }
2353 TEST_UTIL.getMiniHBaseCluster().getMaster().deleteNamespace(namespace);
2354 }
2355
2356 @Test
2357 public void testTruncatePerms() throws Exception {
2358 try {
2359 List<UserPermission> existingPerms = AccessControlClient.getUserPermissions(conf, TEST_TABLE
2360 .getTableName().getNameAsString());
2361 assertTrue(existingPerms != null);
2362 assertTrue(existingPerms.size() > 1);
2363 TEST_UTIL.getHBaseAdmin().disableTable(TEST_TABLE.getTableName());
2364 TEST_UTIL.getHBaseAdmin().truncateTable(TEST_TABLE.getTableName(), true);
2365 List<UserPermission> perms = AccessControlClient.getUserPermissions(conf, TEST_TABLE
2366 .getTableName().getNameAsString());
2367 assertTrue(perms != null);
2368 assertEquals(existingPerms.size(), perms.size());
2369 } catch (Throwable e) {
2370 throw new HBaseIOException(e);
2371 }
2372 }
2373
2374 private void verifyAnyCreate(AccessTestAction action) throws Exception {
2375 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_ADMIN_CF);
2376 verifyDenied(action, USER_NONE, USER_RO, USER_RW);
2377 }
2378
2379 @Test
2380 public void testPrepareAndCleanBulkLoad() throws Exception {
2381 AccessTestAction prepareBulkLoadAction = new AccessTestAction() {
2382 @Override
2383 public Object run() throws Exception {
2384 ACCESS_CONTROLLER.prePrepareBulkLoad(ObserverContext.createAndPrepare(RCP_ENV, null), null);
2385 return null;
2386 }
2387 };
2388 AccessTestAction cleanupBulkLoadAction = new AccessTestAction() {
2389 @Override
2390 public Object run() throws Exception {
2391 ACCESS_CONTROLLER.preCleanupBulkLoad(ObserverContext.createAndPrepare(RCP_ENV, null), null);
2392 return null;
2393 }
2394 };
2395 verifyAnyCreate(prepareBulkLoadAction);
2396 verifyAnyCreate(cleanupBulkLoadAction);
2397 }
2398
2399 @Test
2400 public void testReplicateLogEntries() throws Exception {
2401 AccessTestAction replicateLogEntriesAction = new AccessTestAction() {
2402 @Override
2403 public Object run() throws Exception {
2404 ACCESS_CONTROLLER.preReplicateLogEntries(ObserverContext.createAndPrepare(RSCP_ENV, null),
2405 null, null);
2406 ACCESS_CONTROLLER.postReplicateLogEntries(ObserverContext.createAndPrepare(RSCP_ENV, null),
2407 null, null);
2408 return null;
2409 }
2410 };
2411
2412 verifyAllowed(replicateLogEntriesAction, SUPERUSER, USER_ADMIN);
2413 verifyDenied(replicateLogEntriesAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
2414 }
2415 }