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