1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.security.access;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.fail;
22
23 import java.io.IOException;
24 import java.security.PrivilegedExceptionAction;
25 import java.util.HashMap;
26 import java.util.Map;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.AuthUtil;
32 import org.apache.hadoop.hbase.Coprocessor;
33 import org.apache.hadoop.hbase.HBaseTestingUtility;
34 import org.apache.hadoop.hbase.HColumnDescriptor;
35 import org.apache.hadoop.hbase.HTableDescriptor;
36 import org.apache.hadoop.hbase.TableNotFoundException;
37 import org.apache.hadoop.hbase.client.Delete;
38 import org.apache.hadoop.hbase.client.Get;
39 import org.apache.hadoop.hbase.client.HBaseAdmin;
40 import org.apache.hadoop.hbase.client.HTable;
41 import org.apache.hadoop.hbase.client.Increment;
42 import org.apache.hadoop.hbase.client.Put;
43 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
44 import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
45 import org.apache.hadoop.hbase.security.User;
46 import org.apache.hadoop.hbase.security.access.Permission.Action;
47 import org.apache.hadoop.hbase.testclassification.MediumTests;
48 import org.apache.hadoop.hbase.util.Bytes;
49 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
50 import org.apache.hadoop.hbase.util.TestTableName;
51 import org.apache.log4j.Level;
52 import org.apache.log4j.Logger;
53 import org.junit.After;
54 import org.junit.AfterClass;
55 import org.junit.Before;
56 import org.junit.BeforeClass;
57 import org.junit.Rule;
58 import org.junit.Test;
59 import org.junit.experimental.categories.Category;
60
61 @Category(MediumTests.class)
62 public class TestCellACLWithMultipleVersions extends SecureTestUtil {
63 private static final Log LOG = LogFactory.getLog(TestCellACLWithMultipleVersions.class);
64
65 static {
66 Logger.getLogger(AccessController.class).setLevel(Level.TRACE);
67 Logger.getLogger(AccessControlFilter.class).setLevel(Level.TRACE);
68 Logger.getLogger(TableAuthManager.class).setLevel(Level.TRACE);
69 }
70
71 @Rule
72 public TestTableName TEST_TABLE = new TestTableName();
73 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
74 private static final byte[] TEST_FAMILY1 = Bytes.toBytes("f1");
75 private static final byte[] TEST_FAMILY2 = Bytes.toBytes("f2");
76 private static final byte[] TEST_ROW = Bytes.toBytes("cellpermtest");
77 private static final byte[] TEST_Q1 = Bytes.toBytes("q1");
78 private static final byte[] TEST_Q2 = Bytes.toBytes("q2");
79 private static final byte[] ZERO = Bytes.toBytes(0L);
80 private static final byte[] ONE = Bytes.toBytes(1L);
81 private static final byte[] TWO = Bytes.toBytes(2L);
82
83 private static Configuration conf;
84
85 private static final String GROUP = "group";
86 private static User GROUP_USER;
87 private static User USER_OWNER;
88 private static User USER_OTHER;
89 private static User USER_OTHER2;
90
91 private static String[] usersAndGroups;
92
93 @BeforeClass
94 public static void setupBeforeClass() throws Exception {
95
96 conf = TEST_UTIL.getConfiguration();
97
98 enableSecurity(conf);
99
100 verifyConfiguration(conf);
101
102
103 conf.setBoolean(AccessControlConstants.CF_ATTRIBUTE_EARLY_OUT, false);
104
105 TEST_UTIL.startMiniCluster();
106 MasterCoprocessorHost cpHost = TEST_UTIL.getMiniHBaseCluster()
107 .getMaster().getCoprocessorHost();
108 cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
109 AccessController ac = (AccessController)
110 cpHost.findCoprocessor(AccessController.class.getName());
111 cpHost.createEnvironment(AccessController.class, ac, Coprocessor.PRIORITY_HIGHEST, 1, conf);
112 RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
113 .getCoprocessorHost();
114 rsHost.createEnvironment(AccessController.class, ac, Coprocessor.PRIORITY_HIGHEST, 1, conf);
115
116
117 TEST_UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME.getName());
118
119
120 USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
121 USER_OTHER = User.createUserForTesting(conf, "other", new String[0]);
122 USER_OTHER2 = User.createUserForTesting(conf, "other2", new String[0]);
123 GROUP_USER = User.createUserForTesting(conf, "group_user", new String[] { GROUP });
124
125 usersAndGroups = new String[] { USER_OTHER.getShortName(), AuthUtil.toGroupEntry(GROUP) };
126 }
127
128 @AfterClass
129 public static void tearDownAfterClass() throws Exception {
130 TEST_UTIL.shutdownMiniCluster();
131 }
132
133 @Before
134 public void setUp() throws Exception {
135
136 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
137 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
138 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY1);
139 hcd.setMaxVersions(4);
140 htd.setOwner(USER_OWNER);
141 htd.addFamily(hcd);
142 hcd = new HColumnDescriptor(TEST_FAMILY2);
143 hcd.setMaxVersions(4);
144 htd.setOwner(USER_OWNER);
145 htd.addFamily(hcd);
146 admin.createTable(htd, new byte[][] { Bytes.toBytes("s") });
147 TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName().getName());
148 }
149
150 @Test
151 public void testCellPermissionwithVersions() throws Exception {
152
153
154 final Map<String, Permission> writePerms = prepareCellPermissions(usersAndGroups, Action.WRITE);
155 final Map<String, Permission> readPerms = prepareCellPermissions(usersAndGroups, Action.READ);
156 verifyAllowed(new AccessTestAction() {
157 @Override
158 public Object run() throws Exception {
159 HTable t = new HTable(conf, TEST_TABLE.getTableName());
160 try {
161 Put p;
162
163 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
164 p.setACL(writePerms);
165 t.put(p);
166
167 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
168 p.setACL(readPerms);
169 t.put(p);
170 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
171 p.setACL(writePerms);
172 t.put(p);
173 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
174 p.setACL(readPerms);
175 t.put(p);
176 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
177 p.setACL(writePerms);
178 t.put(p);
179 } finally {
180 t.close();
181 }
182 return null;
183 }
184 }, USER_OWNER);
185
186
187
188 AccessTestAction getQ1 = new AccessTestAction() {
189 @Override
190 public Object run() throws Exception {
191 Get get = new Get(TEST_ROW);
192 get.setMaxVersions(10);
193 HTable t = new HTable(conf, TEST_TABLE.getTableName());
194 try {
195 return t.get(get).listCells();
196 } finally {
197 t.close();
198 }
199 }
200 };
201
202 AccessTestAction get2 = new AccessTestAction() {
203 @Override
204 public Object run() throws Exception {
205 Get get = new Get(TEST_ROW);
206 get.setMaxVersions(10);
207 HTable t = new HTable(conf, TEST_TABLE.getTableName());
208 try {
209 return t.get(get).listCells();
210 } finally {
211 t.close();
212 }
213 }
214 };
215
216
217 verifyAllowed(GROUP_USER, getQ1, 2);
218 verifyAllowed(USER_OTHER, getQ1, 2);
219
220
221
222 verifyAllowed(new AccessTestAction() {
223 @Override
224 public Object run() throws Exception {
225 HTable t = new HTable(conf, TEST_TABLE.getTableName());
226 try {
227 Put p;
228 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
229 p.setACL(writePerms);
230 t.put(p);
231 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
232 p.setACL(readPerms);
233 t.put(p);
234 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
235 p.setACL(writePerms);
236 t.put(p);
237 } finally {
238 t.close();
239 }
240 return null;
241 }
242 }, USER_OWNER);
243
244
245 verifyAllowed(USER_OTHER, get2, 1);
246 verifyAllowed(GROUP_USER, get2, 1);
247 }
248
249 private Map<String, Permission> prepareCellPermissions(String[] users, Action... action) {
250 Map<String, Permission> perms = new HashMap<String, Permission>(2);
251 for (String user : users) {
252 perms.put(user, new Permission(action));
253 }
254 return perms;
255 }
256
257 @Test
258 public void testCellPermissionsWithDeleteMutipleVersions() throws Exception {
259
260 final byte[] TEST_ROW1 = Bytes.toBytes("r1");
261 final byte[] TEST_ROW2 = Bytes.toBytes("r2");
262 final byte[] TEST_Q1 = Bytes.toBytes("q1");
263 final byte[] TEST_Q2 = Bytes.toBytes("q2");
264 final byte[] ZERO = Bytes.toBytes(0L);
265
266
267 final User user1 = User.createUserForTesting(conf, "user1", new String[0]);
268 final User user2 = User.createUserForTesting(conf, "user2", new String[0]);
269
270 verifyAllowed(new AccessTestAction() {
271 @Override
272 public Object run() throws Exception {
273 HTable t = new HTable(conf, TEST_TABLE.getTableName());
274 try {
275
276 Put p = new Put(TEST_ROW1);
277 p.add(TEST_FAMILY1, TEST_Q1, ZERO);
278 p.add(TEST_FAMILY1, TEST_Q2, ZERO);
279 p.setACL(user1.getShortName(), new Permission(Permission.Action.READ,
280 Permission.Action.WRITE));
281 t.put(p);
282
283 p = new Put(TEST_ROW2);
284 p.add(TEST_FAMILY1, TEST_Q1, ZERO);
285 p.add(TEST_FAMILY1, TEST_Q2, ZERO);
286 p.setACL(user1.getShortName(), new Permission(Permission.Action.READ,
287 Permission.Action.WRITE));
288 t.put(p);
289 } finally {
290 t.close();
291 }
292 return null;
293 }
294 }, USER_OWNER);
295
296 verifyAllowed(new AccessTestAction() {
297 @Override
298 public Object run() throws Exception {
299 HTable t = new HTable(conf, TEST_TABLE.getTableName());
300 try {
301
302 Put p = new Put(TEST_ROW1);
303 p.add(TEST_FAMILY1, TEST_Q1, ZERO);
304 p.add(TEST_FAMILY1, TEST_Q2, ZERO);
305 Map<String, Permission> perms =
306 prepareCellPermissions(new String[] { user1.getShortName(), user2.getShortName(),
307 AuthUtil.toGroupEntry(GROUP) }, Action.READ, Action.WRITE);
308 p.setACL(perms);
309 t.put(p);
310
311 p = new Put(TEST_ROW2);
312 p.add(TEST_FAMILY1, TEST_Q1, ZERO);
313 p.add(TEST_FAMILY1, TEST_Q2, ZERO);
314 p.setACL(perms);
315 t.put(p);
316 } finally {
317 t.close();
318 }
319 return null;
320 }
321 }, user1);
322
323
324
325 user1.runAs(new PrivilegedExceptionAction<Void>() {
326 @Override
327 public Void run() throws Exception {
328 HTable t = new HTable(conf, TEST_TABLE.getTableName());
329 try {
330 Delete d = new Delete(TEST_ROW1);
331 d.deleteColumns(TEST_FAMILY1, TEST_Q1);
332 d.deleteColumns(TEST_FAMILY1, TEST_Q2);
333 t.delete(d);
334 } finally {
335 t.close();
336 }
337 return null;
338 }
339 });
340
341
342 verifyUserDeniedForDeleteMultipleVersions(user2, TEST_ROW2, TEST_Q1, TEST_Q2);
343
344
345
346 verifyUserDeniedForDeleteMultipleVersions(GROUP_USER, TEST_ROW2, TEST_Q1, TEST_Q2);
347
348
349 user1.runAs(new PrivilegedExceptionAction<Void>() {
350 @Override
351 public Void run() throws Exception {
352 HTable t = new HTable(conf, TEST_TABLE.getTableName());
353 try {
354 Delete d = new Delete(TEST_ROW2);
355 d.deleteFamily(TEST_FAMILY1);
356 t.delete(d);
357 } finally {
358 t.close();
359 }
360 return null;
361 }
362 });
363 }
364
365 private void verifyUserDeniedForDeleteMultipleVersions(final User user, final byte[] row,
366 final byte[] q1, final byte[] q2) throws IOException, InterruptedException {
367 user.runAs(new PrivilegedExceptionAction<Void>() {
368 @Override
369 public Void run() throws Exception {
370 HTable t = new HTable(conf, TEST_TABLE.getTableName());
371 try {
372 Delete d = new Delete(row);
373 d.deleteColumns(TEST_FAMILY1, q1);
374 d.deleteColumns(TEST_FAMILY1, q2);
375 t.delete(d);
376 fail(user.getShortName() + " should not be allowed to delete the row");
377 } catch (Exception e) {
378
379 } finally {
380 t.close();
381 }
382 return null;
383 }
384 });
385 }
386
387 @Test
388 public void testDeleteWithFutureTimestamp() throws Exception {
389
390
391 verifyAllowed(new AccessTestAction() {
392 @Override
393 public Object run() throws Exception {
394 HTable t = new HTable(conf, TEST_TABLE.getTableName());
395 try {
396
397 Put p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1,
398 EnvironmentEdgeManager.currentTimeMillis() + 1000000,
399 ZERO);
400 Map<String, Permission> readAndWritePerms =
401 prepareCellPermissions(usersAndGroups, Action.READ, Action.WRITE);
402 p.setACL(prepareCellPermissions(usersAndGroups, Action.READ, Action.WRITE));
403 t.put(p);
404
405 p = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q2, ONE);
406 p.setACL(readAndWritePerms);
407 t.put(p);
408
409 p = new Put(TEST_ROW).add(TEST_FAMILY2, TEST_Q2, ONE);
410 p.setACL(readAndWritePerms);
411 t.put(p);
412
413 } finally {
414 t.close();
415 }
416 return null;
417 }
418 }, USER_OWNER);
419
420
421
422 AccessTestAction getQ1 = new AccessTestAction() {
423 @Override
424 public Object run() throws Exception {
425 Get get = new Get(TEST_ROW).addColumn(TEST_FAMILY1, TEST_Q1);
426 HTable t = new HTable(conf, TEST_TABLE.getTableName());
427 try {
428 return t.get(get).listCells();
429 } finally {
430 t.close();
431 }
432 }
433 };
434
435 AccessTestAction getQ2 = new AccessTestAction() {
436 @Override
437 public Object run() throws Exception {
438 Get get = new Get(TEST_ROW).addColumn(TEST_FAMILY1, TEST_Q2);
439 HTable t = new HTable(conf, TEST_TABLE.getTableName());
440 try {
441 return t.get(get).listCells();
442 } finally {
443 t.close();
444 }
445 }
446 };
447
448 verifyAllowed(getQ1, USER_OWNER, USER_OTHER, GROUP_USER);
449 verifyAllowed(getQ2, USER_OWNER, USER_OTHER, GROUP_USER);
450
451
452
453
454
455 AccessTestAction deleteFamily1 = getDeleteFamilyAction(TEST_FAMILY1);
456 AccessTestAction deleteFamily2 = getDeleteFamilyAction(TEST_FAMILY2);
457
458 verifyAllowed(deleteFamily1, USER_OTHER);
459 verifyAllowed(deleteFamily2, GROUP_USER);
460
461
462
463 verifyAllowed(getQ1, USER_OWNER, USER_OTHER, GROUP_USER);
464
465
466
467 verifyIfNull(getQ2, USER_OTHER, GROUP_USER);
468 }
469
470 private AccessTestAction getDeleteFamilyAction(final byte[] fam) {
471 AccessTestAction deleteFamily = new AccessTestAction() {
472 @Override
473 public Object run() throws Exception {
474 Delete delete = new Delete(TEST_ROW).deleteFamily(fam);
475 HTable t = new HTable(conf, TEST_TABLE.getTableName());
476 try {
477 t.delete(delete);
478 } finally {
479 t.close();
480 }
481 return null;
482 }
483 };
484 return deleteFamily;
485 }
486
487 @Test
488 public void testCellPermissionsWithDeleteWithUserTs() throws Exception {
489 USER_OWNER.runAs(new AccessTestAction() {
490 @Override
491 public Object run() throws Exception {
492 HTable t = new HTable(conf, TEST_TABLE.getTableName());
493 try {
494
495 Put p = new Put(TEST_ROW);
496 p.add(TEST_FAMILY1, TEST_Q1, 123L, ZERO);
497 p.add(TEST_FAMILY1, TEST_Q2, 123L, ZERO);
498 p.setACL(prepareCellPermissions(
499 new String[] { USER_OTHER.getShortName(), AuthUtil.toGroupEntry(GROUP),
500 USER_OTHER2.getShortName() }, Permission.Action.READ, Permission.Action.WRITE));
501 t.put(p);
502
503
504 p = new Put(TEST_ROW);
505 p.add(TEST_FAMILY1, TEST_Q1, 125L, ONE);
506 p.add(TEST_FAMILY1, TEST_Q2, 125L, ONE);
507 p.setACL(prepareCellPermissions(
508 new String[] { USER_OTHER.getShortName(), AuthUtil.toGroupEntry(GROUP) },
509 Action.READ, Action.WRITE));
510 t.put(p);
511
512
513 p = new Put(TEST_ROW);
514 p.add(TEST_FAMILY1, TEST_Q1, 127L, TWO);
515 p.add(TEST_FAMILY1, TEST_Q2, 127L, TWO);
516 p.setACL(prepareCellPermissions(
517 new String[] { USER_OTHER.getShortName(), AuthUtil.toGroupEntry(GROUP) },
518 Action.READ, Action.WRITE));
519 t.put(p);
520
521 return null;
522 } finally {
523 t.close();
524 }
525 }
526 });
527
528
529 USER_OTHER2.runAs(new AccessTestAction() {
530 @Override
531 public Object run() throws Exception {
532 HTable t = new HTable(conf, TEST_TABLE.getTableName());
533 try {
534 Delete d = new Delete(TEST_ROW, 124L);
535 d.deleteColumns(TEST_FAMILY1, TEST_Q1);
536 t.delete(d);
537 } finally {
538 t.close();
539 }
540 return null;
541 }
542 });
543
544
545 USER_OTHER2.runAs(new AccessTestAction() {
546 @Override
547 public Object run() throws Exception {
548 HTable t = new HTable(conf, TEST_TABLE.getTableName());
549 try {
550 Delete d = new Delete(TEST_ROW);
551 d.deleteColumns(TEST_FAMILY1, TEST_Q2, 124L);
552 t.delete(d);
553 } finally {
554 t.close();
555 }
556 return null;
557 }
558 });
559 }
560
561 @Test
562 public void testCellPermissionsWithDeleteExactVersion() throws Exception {
563 final byte[] TEST_ROW1 = Bytes.toBytes("r1");
564 final byte[] TEST_Q1 = Bytes.toBytes("q1");
565 final byte[] TEST_Q2 = Bytes.toBytes("q2");
566 final byte[] ZERO = Bytes.toBytes(0L);
567
568 final User user1 = User.createUserForTesting(conf, "user1", new String[0]);
569 final User user2 = User.createUserForTesting(conf, "user2", new String[0]);
570
571 verifyAllowed(new AccessTestAction() {
572 @Override
573 public Object run() throws Exception {
574 HTable t = new HTable(conf, TEST_TABLE.getTableName());
575 try {
576 Map<String, Permission> permsU1andOwner =
577 prepareCellPermissions(
578 new String[] { user1.getShortName(), USER_OWNER.getShortName() }, Action.READ,
579 Action.WRITE);
580 Map<String, Permission> permsU2andGUandOwner =
581 prepareCellPermissions(
582 new String[] { user2.getShortName(), AuthUtil.toGroupEntry(GROUP),
583 USER_OWNER.getShortName() }, Action.READ, Action.WRITE);
584 Put p = new Put(TEST_ROW1);
585 p.add(TEST_FAMILY1, TEST_Q1, 123, ZERO);
586 p.setACL(permsU1andOwner);
587 t.put(p);
588 p = new Put(TEST_ROW1);
589 p.add(TEST_FAMILY1, TEST_Q2, 123, ZERO);
590 p.setACL(permsU2andGUandOwner);
591 t.put(p);
592 p = new Put(TEST_ROW1);
593 p.add(TEST_FAMILY2, TEST_Q1, 123, ZERO);
594 p.add(TEST_FAMILY2, TEST_Q2, 123, ZERO);
595 p.setACL(permsU2andGUandOwner);
596 t.put(p);
597
598 p = new Put(TEST_ROW1);
599 p.add(TEST_FAMILY2, TEST_Q1, 125, ZERO);
600 p.add(TEST_FAMILY2, TEST_Q2, 125, ZERO);
601 p.setACL(permsU1andOwner);
602 t.put(p);
603
604 p = new Put(TEST_ROW1);
605 p.add(TEST_FAMILY1, TEST_Q1, 127, ZERO);
606 p.setACL(permsU2andGUandOwner);
607 t.put(p);
608 p = new Put(TEST_ROW1);
609 p.add(TEST_FAMILY1, TEST_Q2, 127, ZERO);
610 p.setACL(permsU1andOwner);
611 t.put(p);
612 p = new Put(TEST_ROW1);
613 p.add(TEST_FAMILY2, TEST_Q1, 129, ZERO);
614 p.add(TEST_FAMILY2, TEST_Q2, 129, ZERO);
615 p.setACL(permsU1andOwner);
616 t.put(p);
617 } finally {
618 t.close();
619 }
620 return null;
621 }
622 }, USER_OWNER);
623
624
625
626 user1.runAs(new PrivilegedExceptionAction<Void>() {
627 @Override
628 public Void run() throws Exception {
629 HTable t = new HTable(conf, TEST_TABLE.getTableName());
630 try {
631 Delete d = new Delete(TEST_ROW1);
632 d.deleteColumn(TEST_FAMILY1, TEST_Q1, 123);
633 d.deleteColumn(TEST_FAMILY1, TEST_Q2);
634 d.deleteFamilyVersion(TEST_FAMILY2, 125);
635 t.delete(d);
636 } finally {
637 t.close();
638 }
639 return null;
640 }
641 });
642
643 verifyUserDeniedForDeleteExactVersion(user2, TEST_ROW1, TEST_Q1, TEST_Q2);
644 verifyUserDeniedForDeleteExactVersion(GROUP_USER, TEST_ROW1, TEST_Q1, TEST_Q2);
645 }
646
647 private void verifyUserDeniedForDeleteExactVersion(final User user, final byte[] row,
648 final byte[] q1, final byte[] q2) throws IOException, InterruptedException {
649 user.runAs(new PrivilegedExceptionAction<Void>() {
650 @Override
651 public Void run() throws Exception {
652 HTable t = new HTable(conf, TEST_TABLE.getTableName());
653 try {
654 Delete d = new Delete(row, 127);
655 d.deleteColumns(TEST_FAMILY1, q1);
656 d.deleteColumns(TEST_FAMILY1, q2);
657 d.deleteFamily(TEST_FAMILY2, 129);
658 t.delete(d);
659 fail(user.getShortName() + " can not do the delete");
660 } catch (Exception e) {
661
662 } finally {
663 t.close();
664 }
665 return null;
666 }
667 });
668 }
669
670 @Test
671 public void testCellPermissionsForIncrementWithMultipleVersions() throws Exception {
672 final byte[] TEST_ROW1 = Bytes.toBytes("r1");
673 final byte[] TEST_Q1 = Bytes.toBytes("q1");
674 final byte[] TEST_Q2 = Bytes.toBytes("q2");
675 final byte[] ZERO = Bytes.toBytes(0L);
676
677 final User user1 = User.createUserForTesting(conf, "user1", new String[0]);
678 final User user2 = User.createUserForTesting(conf, "user2", new String[0]);
679
680 verifyAllowed(new AccessTestAction() {
681 @Override
682 public Object run() throws Exception {
683 HTable t = new HTable(conf, TEST_TABLE.getTableName());
684 try {
685 Map<String, Permission> permsU1andOwner =
686 prepareCellPermissions(
687 new String[] { user1.getShortName(), USER_OWNER.getShortName() }, Action.READ,
688 Action.WRITE);
689 Map<String, Permission> permsU2andGUandOwner =
690 prepareCellPermissions(
691 new String[] { user2.getShortName(), AuthUtil.toGroupEntry(GROUP),
692 USER_OWNER.getShortName() }, Action.READ, Action.WRITE);
693 Put p = new Put(TEST_ROW1);
694 p.add(TEST_FAMILY1, TEST_Q1, 123, ZERO);
695 p.setACL(permsU1andOwner);
696 t.put(p);
697 p = new Put(TEST_ROW1);
698 p.add(TEST_FAMILY1, TEST_Q2, 123, ZERO);
699 p.setACL(permsU2andGUandOwner);
700 t.put(p);
701
702 p = new Put(TEST_ROW1);
703 p.add(TEST_FAMILY1, TEST_Q1, 127, ZERO);
704 p.setACL(permsU2andGUandOwner);
705 t.put(p);
706 p = new Put(TEST_ROW1);
707 p.add(TEST_FAMILY1, TEST_Q2, 127, ZERO);
708 p.setACL(permsU1andOwner);
709 t.put(p);
710 } finally {
711 t.close();
712 }
713 return null;
714 }
715 }, USER_OWNER);
716
717
718 user1.runAs(new PrivilegedExceptionAction<Void>() {
719 @Override
720 public Void run() throws Exception {
721 HTable t = new HTable(conf, TEST_TABLE.getTableName());
722 try {
723 Increment inc = new Increment(TEST_ROW1);
724 inc.setTimeRange(0, 123);
725 inc.addColumn(TEST_FAMILY1, TEST_Q1, 2L);
726 t.increment(inc);
727 t.incrementColumnValue(TEST_ROW1, TEST_FAMILY1, TEST_Q2, 1L);
728 } finally {
729 t.close();
730 }
731 return null;
732 }
733 });
734
735 verifyUserDeniedForIncrementMultipleVersions(user2, TEST_ROW1, TEST_Q2);
736 verifyUserDeniedForIncrementMultipleVersions(GROUP_USER, TEST_ROW1, TEST_Q2);
737 }
738
739 private void verifyUserDeniedForIncrementMultipleVersions(final User user,
740 final byte[] row, final byte[] q1) throws IOException, InterruptedException {
741 user.runAs(new PrivilegedExceptionAction<Void>() {
742 @Override
743 public Void run() throws Exception {
744 HTable t = new HTable(conf, TEST_TABLE.getTableName());
745 try {
746 Increment inc = new Increment(row);
747 inc.setTimeRange(0, 127);
748 inc.addColumn(TEST_FAMILY1, q1, 2L);
749 t.increment(inc);
750 fail(user.getShortName() + " cannot do the increment.");
751 } catch (Exception e) {
752
753 } finally {
754 t.close();
755 }
756 return null;
757 }
758 });
759 }
760
761 @Test
762 public void testCellPermissionsForPutWithMultipleVersions() throws Exception {
763 final byte[] TEST_ROW1 = Bytes.toBytes("r1");
764 final byte[] TEST_Q1 = Bytes.toBytes("q1");
765 final byte[] TEST_Q2 = Bytes.toBytes("q2");
766 final byte[] ZERO = Bytes.toBytes(0L);
767
768 final User user1 = User.createUserForTesting(conf, "user1", new String[0]);
769 final User user2 = User.createUserForTesting(conf, "user2", new String[0]);
770
771 verifyAllowed(new AccessTestAction() {
772 @Override
773 public Object run() throws Exception {
774 HTable t = new HTable(conf, TEST_TABLE.getTableName());
775 try {
776 Map<String, Permission> permsU1andOwner =
777 prepareCellPermissions(
778 new String[] { user1.getShortName(), USER_OWNER.getShortName() }, Action.READ,
779 Action.WRITE);
780 Map<String, Permission> permsU2andGUandOwner =
781 prepareCellPermissions(
782 new String[] { user1.getShortName(), AuthUtil.toGroupEntry(GROUP),
783 USER_OWNER.getShortName() }, Action.READ, Action.WRITE);
784 permsU2andGUandOwner.put(user2.getShortName(), new Permission(Permission.Action.READ,
785 Permission.Action.WRITE));
786 permsU2andGUandOwner.put(USER_OWNER.getShortName(), new Permission(
787 Permission.Action.READ, Permission.Action.WRITE));
788 Put p = new Put(TEST_ROW1);
789 p.add(TEST_FAMILY1, TEST_Q1, 123, ZERO);
790 p.setACL(permsU1andOwner);
791 t.put(p);
792 p = new Put(TEST_ROW1);
793 p.add(TEST_FAMILY1, TEST_Q2, 123, ZERO);
794 p.setACL(permsU2andGUandOwner);
795 t.put(p);
796
797 p = new Put(TEST_ROW1);
798 p.add(TEST_FAMILY1, TEST_Q1, 127, ZERO);
799 p.setACL(permsU2andGUandOwner);
800 t.put(p);
801 p = new Put(TEST_ROW1);
802 p.add(TEST_FAMILY1, TEST_Q2, 127, ZERO);
803 p.setACL(permsU1andOwner);
804 t.put(p);
805 } finally {
806 t.close();
807 }
808 return null;
809 }
810 }, USER_OWNER);
811
812
813
814
815 user1.runAs(new PrivilegedExceptionAction<Void>() {
816 @Override
817 public Void run() throws Exception {
818 HTable t = new HTable(conf, TEST_TABLE.getTableName());
819 try {
820 Put p = new Put(TEST_ROW1);
821 p.add(TEST_FAMILY1, TEST_Q1, 125, ZERO);
822 p.add(TEST_FAMILY1, TEST_Q2, ZERO);
823 p.setACL(user2.getShortName(), new Permission(Permission.Action.READ,
824 Permission.Action.WRITE));
825 t.put(p);
826 } finally {
827 t.close();
828 }
829 return null;
830 }
831 });
832
833
834 verifyUserDeniedForPutMultipleVersions(user2, TEST_ROW1, TEST_Q1, TEST_Q2, ZERO);
835 verifyUserDeniedForPutMultipleVersions(GROUP_USER, TEST_ROW1, TEST_Q1, TEST_Q2, ZERO);
836 }
837
838 private void verifyUserDeniedForPutMultipleVersions(final User user, final byte[] row,
839 final byte[] q1, final byte[] q2, final byte[] val) throws IOException,
840 InterruptedException {
841 user.runAs(new PrivilegedExceptionAction<Void>() {
842 @Override
843 public Void run() throws Exception {
844 HTable t = new HTable(conf, TEST_TABLE.getTableName());
845 try {
846 Put p = new Put(row);
847
848 p.add(TEST_FAMILY1, q1, 124, val);
849 p.add(TEST_FAMILY1, q2, val);
850 t.put(p);
851 fail(user.getShortName() + " cannot do the put.");
852 } catch (Exception e) {
853
854 } finally {
855 t.close();
856 }
857 return null;
858 }
859 });
860 }
861
862 @Test
863 public void testCellPermissionsForCheckAndDelete() throws Exception {
864 final byte[] TEST_ROW1 = Bytes.toBytes("r1");
865 final byte[] TEST_Q3 = Bytes.toBytes("q3");
866 final byte[] ZERO = Bytes.toBytes(0L);
867
868 final User user1 = User.createUserForTesting(conf, "user1", new String[0]);
869 final User user2 = User.createUserForTesting(conf, "user2", new String[0]);
870
871 verifyAllowed(new AccessTestAction() {
872 @Override
873 public Object run() throws Exception {
874 HTable t = new HTable(conf, TEST_TABLE.getTableName());
875 try {
876 Map<String, Permission> permsU1andOwner =
877 prepareCellPermissions(
878 new String[] { user1.getShortName(), USER_OWNER.getShortName() }, Action.READ,
879 Action.WRITE);
880 Map<String, Permission> permsU1andU2andGUandOwner =
881 prepareCellPermissions(new String[] { user1.getShortName(), user2.getShortName(),
882 AuthUtil.toGroupEntry(GROUP), USER_OWNER.getShortName() }, Action.READ,
883 Action.WRITE);
884 Map<String, Permission> permsU1andU2andGU =
885 prepareCellPermissions(new String[] { user1.getShortName(), user2.getShortName(),
886 AuthUtil.toGroupEntry(GROUP) }, Action.READ, Action.WRITE);
887
888 Put p = new Put(TEST_ROW1);
889 p.add(TEST_FAMILY1, TEST_Q1, 120, ZERO);
890 p.add(TEST_FAMILY1, TEST_Q2, 120, ZERO);
891 p.add(TEST_FAMILY1, TEST_Q3, 120, ZERO);
892 p.setACL(permsU1andU2andGUandOwner);
893 t.put(p);
894
895 p = new Put(TEST_ROW1);
896 p.add(TEST_FAMILY1, TEST_Q1, 123, ZERO);
897 p.add(TEST_FAMILY1, TEST_Q2, 123, ZERO);
898 p.add(TEST_FAMILY1, TEST_Q3, 123, ZERO);
899 p.setACL(permsU1andOwner);
900 t.put(p);
901
902 p = new Put(TEST_ROW1);
903 p.add(TEST_FAMILY1, TEST_Q1, 127, ZERO);
904 p.setACL(permsU1andU2andGU);
905 t.put(p);
906
907 p = new Put(TEST_ROW1);
908 p.add(TEST_FAMILY1, TEST_Q2, 127, ZERO);
909 p.setACL(user2.getShortName(), new Permission(Permission.Action.READ));
910 t.put(p);
911
912 p = new Put(TEST_ROW1);
913 p.add(TEST_FAMILY1, TEST_Q3, 127, ZERO);
914 p.setACL(AuthUtil.toGroupEntry(GROUP), new Permission(Permission.Action.READ));
915 t.put(p);
916 } finally {
917 t.close();
918 }
919 return null;
920 }
921 }, USER_OWNER);
922
923
924
925 user1.runAs(new PrivilegedExceptionAction<Void>() {
926 @Override
927 public Void run() throws Exception {
928 HTable t = new HTable(conf, TEST_TABLE.getTableName());
929 try {
930 Delete d = new Delete(TEST_ROW1);
931 d.deleteColumns(TEST_FAMILY1, TEST_Q1, 120);
932 t.checkAndDelete(TEST_ROW1, TEST_FAMILY1, TEST_Q1, ZERO, d);
933 } finally {
934 t.close();
935 }
936 return null;
937 }
938 });
939
940
941 verifyUserDeniedForCheckAndDelete(user2, TEST_ROW1, ZERO);
942
943
944
945
946 verifyUserDeniedForCheckAndDelete(GROUP_USER, TEST_ROW1, ZERO);
947
948
949
950
951 verifyUserAllowedforCheckAndDelete(user2, TEST_ROW1, TEST_Q2, ZERO);
952
953
954
955
956
957 verifyUserAllowedforCheckAndDelete(GROUP_USER, TEST_ROW1, TEST_Q3, ZERO);
958 }
959
960 private void verifyUserAllowedforCheckAndDelete(final User user, final byte[] row,
961 final byte[] q1, final byte[] value) throws IOException, InterruptedException {
962 user.runAs(new PrivilegedExceptionAction<Void>() {
963 @Override
964 public Void run() throws Exception {
965 HTable t = new HTable(conf, TEST_TABLE.getTableName());
966 try {
967 Delete d = new Delete(row);
968 d.deleteColumn(TEST_FAMILY1, q1, 120);
969 t.checkAndDelete(row, TEST_FAMILY1, q1, value, d);
970 } finally {
971 t.close();
972 }
973 return null;
974 }
975 });
976 }
977
978 private void verifyUserDeniedForCheckAndDelete(final User user, final byte[] row,
979 final byte[] value) throws IOException, InterruptedException {
980 user.runAs(new PrivilegedExceptionAction<Void>() {
981 @Override
982 public Void run() throws Exception {
983 HTable t = new HTable(conf, TEST_TABLE.getTableName());
984 try {
985 Delete d = new Delete(row);
986 d.deleteColumns(TEST_FAMILY1, TEST_Q1);
987 t.checkAndDelete(row, TEST_FAMILY1, TEST_Q1, value, d);
988 fail(user.getShortName() + " should not be allowed to do checkAndDelete");
989 } catch (Exception e) {
990 } finally {
991 t.close();
992 }
993 return null;
994 }
995 });
996 }
997
998 @After
999 public void tearDown() throws Exception {
1000
1001 try {
1002 TEST_UTIL.deleteTable(TEST_TABLE.getTableName());
1003 } catch (TableNotFoundException ex) {
1004
1005 LOG.info("Test deleted table " + TEST_TABLE.getTableName());
1006 }
1007 assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName()).size());
1008 }
1009 }