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