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