1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.security.visibility;
19
20 import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_FAMILY;
21 import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME;
22 import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABEL_QUALIFIER;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29
30 import java.io.IOException;
31 import java.security.PrivilegedExceptionAction;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.hbase.Cell;
37 import org.apache.hadoop.hbase.CellScanner;
38 import org.apache.hadoop.hbase.HBaseTestingUtility;
39 import org.apache.hadoop.hbase.HColumnDescriptor;
40 import org.apache.hadoop.hbase.HConstants;
41 import org.apache.hadoop.hbase.HTableDescriptor;
42 import org.apache.hadoop.hbase.MediumTests;
43 import org.apache.hadoop.hbase.TableName;
44 import org.apache.hadoop.hbase.client.Append;
45 import org.apache.hadoop.hbase.client.Get;
46 import org.apache.hadoop.hbase.client.HBaseAdmin;
47 import org.apache.hadoop.hbase.client.HTable;
48 import org.apache.hadoop.hbase.client.Increment;
49 import org.apache.hadoop.hbase.client.Put;
50 import org.apache.hadoop.hbase.client.Result;
51 import org.apache.hadoop.hbase.client.ResultScanner;
52 import org.apache.hadoop.hbase.client.RowMutations;
53 import org.apache.hadoop.hbase.client.Scan;
54 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionActionResult;
55 import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
56 import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
57 import org.apache.hadoop.hbase.regionserver.BloomType;
58 import org.apache.hadoop.hbase.regionserver.HRegion;
59 import org.apache.hadoop.hbase.regionserver.HRegionServer;
60 import org.apache.hadoop.hbase.security.User;
61 import org.apache.hadoop.hbase.util.Bytes;
62 import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
63 import org.junit.After;
64 import org.junit.AfterClass;
65 import org.junit.Assert;
66 import org.junit.BeforeClass;
67 import org.junit.Rule;
68 import org.junit.Test;
69 import org.junit.experimental.categories.Category;
70 import org.junit.rules.TestName;
71
72 import com.google.protobuf.ByteString;
73
74
75
76
77 @Category(MediumTests.class)
78 public class TestVisibilityLabels {
79
80 private static final String TOPSECRET = "topsecret";
81 private static final String PUBLIC = "public";
82 private static final String PRIVATE = "private";
83 private static final String CONFIDENTIAL = "confidential";
84 private static final String SECRET = "secret";
85 public static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
86 private static final byte[] row1 = Bytes.toBytes("row1");
87 private static final byte[] row2 = Bytes.toBytes("row2");
88 private static final byte[] row3 = Bytes.toBytes("row3");
89 private static final byte[] row4 = Bytes.toBytes("row4");
90 private final static byte[] fam = Bytes.toBytes("info");
91 private final static byte[] qual = Bytes.toBytes("qual");
92 private final static byte[] value = Bytes.toBytes("value");
93 public static Configuration conf;
94
95 private volatile boolean killedRS = false;
96 @Rule
97 public final TestName TEST_NAME = new TestName();
98 public static User SUPERUSER;
99
100 @BeforeClass
101 public static void setupBeforeClass() throws Exception {
102
103 conf = TEST_UTIL.getConfiguration();
104 conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
105 conf.setBoolean("hbase.online.schema.update.enable", true);
106 conf.setInt("hfile.format.version", 3);
107 conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
108 conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
109 conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
110 ScanLabelGenerator.class);
111 conf.set("hbase.superuser", "admin");
112 TEST_UTIL.startMiniCluster(2);
113 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
114
115
116 TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
117 addLabels();
118 }
119
120 @AfterClass
121 public static void tearDownAfterClass() throws Exception {
122 TEST_UTIL.shutdownMiniCluster();
123 }
124
125 @After
126 public void tearDown() throws Exception {
127 killedRS = false;
128 }
129
130 @Test
131 public void testSimpleVisibilityLabels() throws Exception {
132 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
133 HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "|" + CONFIDENTIAL,
134 PRIVATE + "|" + CONFIDENTIAL);
135 try {
136 Scan s = new Scan();
137 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL, PRIVATE));
138 ResultScanner scanner = table.getScanner(s);
139 Result[] next = scanner.next(3);
140
141 assertTrue(next.length == 2);
142 CellScanner cellScanner = next[0].cellScanner();
143 cellScanner.advance();
144 Cell current = cellScanner.current();
145 assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
146 current.getRowLength(), row1, 0, row1.length));
147 cellScanner = next[1].cellScanner();
148 cellScanner.advance();
149 current = cellScanner.current();
150 assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
151 current.getRowLength(), row2, 0, row2.length));
152 } finally {
153 if (table != null) {
154 table.close();
155 }
156 }
157 }
158
159 @Test
160 public void testVisibilityLabelsWithComplexLabels() throws Exception {
161 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
162 HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
163 + ")" + "&" + "!" + TOPSECRET, "(" + PRIVATE + "&" + CONFIDENTIAL + "&" + SECRET + ")", "("
164 + PRIVATE + "&" + CONFIDENTIAL + "&" + SECRET + ")", "(" + PRIVATE + "&" + CONFIDENTIAL
165 + "&" + SECRET + ")");
166 try {
167 Scan s = new Scan();
168 s.setAuthorizations(new Authorizations(TOPSECRET, CONFIDENTIAL, PRIVATE, PUBLIC, SECRET));
169 ResultScanner scanner = table.getScanner(s);
170 Result[] next = scanner.next(4);
171 assertEquals(3, next.length);
172 CellScanner cellScanner = next[0].cellScanner();
173 cellScanner.advance();
174 Cell current = cellScanner.current();
175 assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
176 current.getRowLength(), row2, 0, row2.length));
177 cellScanner = next[1].cellScanner();
178 cellScanner.advance();
179 current = cellScanner.current();
180 assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
181 current.getRowLength(), row3, 0, row3.length));
182 cellScanner = next[2].cellScanner();
183 cellScanner.advance();
184 current = cellScanner.current();
185 assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
186 current.getRowLength(), row4, 0, row4.length));
187 } finally {
188 if (table != null) {
189 table.close();
190 }
191 }
192 }
193
194 @Test
195 public void testVisibilityLabelsThatDoesNotPassTheCriteria() throws Exception {
196 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
197 HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
198 + ")", PRIVATE);
199 try {
200 Scan s = new Scan();
201 s.setAuthorizations(new Authorizations(PUBLIC));
202 ResultScanner scanner = table.getScanner(s);
203 Result[] next = scanner.next(3);
204 assertTrue(next.length == 0);
205 } finally {
206 if (table != null) {
207 table.close();
208 }
209 }
210 }
211
212 @Test
213 public void testVisibilityLabelsInPutsThatDoesNotMatchAnyDefinedLabels() throws Exception {
214 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
215 try {
216 createTableAndWriteDataWithLabels(tableName, "SAMPLE_LABEL", "TEST");
217 fail("Should have failed with failed sanity check exception");
218 } catch (Exception e) {
219 }
220 }
221
222 @Test
223 public void testVisibilityLabelsInScanThatDoesNotMatchAnyDefinedLabels() throws Exception {
224 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
225 HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
226 + ")", PRIVATE);
227 try {
228 Scan s = new Scan();
229 s.setAuthorizations(new Authorizations("SAMPLE"));
230 ResultScanner scanner = table.getScanner(s);
231 Result[] next = scanner.next(3);
232 assertTrue(next.length == 0);
233 } finally {
234 if (table != null) {
235 table.close();
236 }
237 }
238 }
239
240 @Test
241 public void testVisibilityLabelsWithGet() throws Exception {
242 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
243 HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL + "&!"
244 + PRIVATE, SECRET + "&" + CONFIDENTIAL + "&" + PRIVATE);
245 try {
246 Get get = new Get(row1);
247 get.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
248 Result result = table.get(get);
249 assertTrue(!result.isEmpty());
250 Cell cell = result.getColumnLatestCell(fam, qual);
251 assertTrue(Bytes.equals(value, 0, value.length, cell.getValueArray(), cell.getValueOffset(),
252 cell.getValueLength()));
253 } finally {
254 if (table != null) {
255 table.close();
256 }
257 }
258 }
259
260 @Test
261 public void testVisibilityLabelsOnKillingOfRSContainingLabelsTable() throws Exception {
262 List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
263 .getRegionServerThreads();
264 int liveRS = 0;
265 for (RegionServerThread rsThreads : regionServerThreads) {
266 if (!rsThreads.getRegionServer().isAborted()) {
267 liveRS++;
268 }
269 }
270 if (liveRS == 1) {
271 TEST_UTIL.getHBaseCluster().startRegionServer();
272 }
273 Thread t1 = new Thread() {
274 public void run() {
275 List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
276 .getRegionServerThreads();
277 for (RegionServerThread rsThread : regionServerThreads) {
278 List<HRegion> onlineRegions = rsThread.getRegionServer().getOnlineRegions(
279 LABELS_TABLE_NAME);
280 if (onlineRegions.size() > 0) {
281 rsThread.getRegionServer().abort("Aborting ");
282 killedRS = true;
283 break;
284 }
285 }
286 }
287
288 };
289 t1.start();
290 final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
291 Thread t = new Thread() {
292 public void run() {
293 try {
294 while (!killedRS) {
295 Thread.sleep(1);
296 }
297 createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL + ")",
298 PRIVATE);
299 } catch (Exception e) {
300 }
301 }
302 };
303 t.start();
304 regionServerThreads = TEST_UTIL.getHBaseCluster().getRegionServerThreads();
305 while (!killedRS) {
306 Thread.sleep(10);
307 }
308 regionServerThreads = TEST_UTIL.getHBaseCluster().getRegionServerThreads();
309 for (RegionServerThread rsThread : regionServerThreads) {
310 while (true) {
311 if (!rsThread.getRegionServer().isAborted()) {
312 List<HRegion> onlineRegions = rsThread.getRegionServer().getOnlineRegions(
313 LABELS_TABLE_NAME);
314 if (onlineRegions.size() > 0) {
315 break;
316 } else {
317 Thread.sleep(10);
318 }
319 } else {
320 break;
321 }
322 }
323 }
324 TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
325 t.join();
326 HTable table = null;
327 try {
328 table = new HTable(TEST_UTIL.getConfiguration(), tableName);
329 Scan s = new Scan();
330 s.setAuthorizations(new Authorizations(SECRET));
331 ResultScanner scanner = table.getScanner(s);
332 Result[] next = scanner.next(3);
333 assertTrue(next.length == 1);
334 } finally {
335 if (table != null) {
336 table.close();
337 }
338 }
339 }
340
341 @Test(timeout = 60 * 1000)
342 public void testVisibilityLabelsOnRSRestart() throws Exception {
343 final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
344 HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
345 + ")", PRIVATE);
346 List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
347 .getRegionServerThreads();
348 for (RegionServerThread rsThread : regionServerThreads) {
349 rsThread.getRegionServer().abort("Aborting ");
350 }
351
352 RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer();
353 waitForLabelsRegionAvailability(rs.getRegionServer());
354 try {
355 Scan s = new Scan();
356 s.setAuthorizations(new Authorizations(SECRET));
357 ResultScanner scanner = table.getScanner(s);
358 Result[] next = scanner.next(3);
359 assertTrue(next.length == 1);
360 } finally {
361 if (table != null) {
362 table.close();
363 }
364 }
365 }
366
367 @Test(timeout = 60 * 1000)
368 public void testAddVisibilityLabelsOnRSRestart() throws Exception {
369 List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
370 .getRegionServerThreads();
371 for (RegionServerThread rsThread : regionServerThreads) {
372 rsThread.getRegionServer().abort("Aborting ");
373 }
374
375 RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer();
376 waitForLabelsRegionAvailability(rs.getRegionServer());
377 PrivilegedExceptionAction<VisibilityLabelsResponse> action =
378 new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
379 public VisibilityLabelsResponse run() throws Exception {
380 String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, "ABC", "XYZ" };
381 try {
382 VisibilityClient.addLabels(conf, labels);
383 } catch (Throwable t) {
384 throw new IOException(t);
385 }
386 return null;
387 }
388 };
389 SUPERUSER.runAs(action);
390
391 Scan s = new Scan();
392 s.setAuthorizations(new Authorizations(VisibilityUtils.SYSTEM_LABEL));
393 HTable ht = new HTable(conf, LABELS_TABLE_NAME.getName());
394 int i = 0;
395 try {
396 ResultScanner scanner = ht.getScanner(s);
397 while (true) {
398 Result next = scanner.next();
399 if (next == null) {
400 break;
401 }
402 i++;
403 }
404 } finally {
405 if (ht != null) {
406 ht.close();
407 }
408 }
409
410 Assert.assertEquals("The count should be 8", 8, i);
411 }
412
413 private void waitForLabelsRegionAvailability(HRegionServer regionServer) {
414 while (!regionServer.isOnline()) {
415 try {
416 Thread.sleep(10);
417 } catch (InterruptedException e) {
418 }
419 }
420 while (regionServer.getOnlineRegions(LABELS_TABLE_NAME).isEmpty()) {
421 try {
422 Thread.sleep(10);
423 } catch (InterruptedException e) {
424 }
425 }
426 HRegion labelsTableRegion = regionServer.getOnlineRegions(LABELS_TABLE_NAME).get(0);
427 while (labelsTableRegion.isRecovering()) {
428 try {
429 Thread.sleep(10);
430 } catch (InterruptedException e) {
431 }
432 }
433 }
434
435 @Test
436 public void testVisibilityLabelsInGetThatDoesNotMatchAnyDefinedLabels() throws Exception {
437 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
438 HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
439 + ")", PRIVATE);
440 try {
441 Get get = new Get(row1);
442 get.setAuthorizations(new Authorizations("SAMPLE"));
443 Result result = table.get(get);
444 assertTrue(result.isEmpty());
445 } finally {
446 if (table != null) {
447 table.close();
448 }
449 }
450 }
451
452 @Test
453 public void testAddLabels() throws Throwable {
454 PrivilegedExceptionAction<VisibilityLabelsResponse> action =
455 new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
456 public VisibilityLabelsResponse run() throws Exception {
457 String[] labels = { "L1", SECRET, "L2", "invalid~", "L3" };
458 VisibilityLabelsResponse response = null;
459 try {
460 response = VisibilityClient.addLabels(conf, labels);
461 } catch (Throwable e) {
462 fail("Should not have thrown exception");
463 }
464 List<RegionActionResult> resultList = response.getResultList();
465 assertEquals(5, resultList.size());
466 assertTrue(resultList.get(0).getException().getValue().isEmpty());
467 assertEquals("org.apache.hadoop.hbase.security.visibility.LabelAlreadyExistsException",
468 resultList.get(1).getException().getName());
469 assertTrue(resultList.get(2).getException().getValue().isEmpty());
470 assertEquals("org.apache.hadoop.hbase.security.visibility.InvalidLabelException",
471 resultList.get(3).getException().getName());
472 assertTrue(resultList.get(4).getException().getValue().isEmpty());
473 return null;
474 }
475 };
476 SUPERUSER.runAs(action);
477 }
478
479 @Test
480 public void testSetAndGetUserAuths() throws Throwable {
481 final String user = "user1";
482 PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
483 public Void run() throws Exception {
484 String[] auths = { SECRET, CONFIDENTIAL };
485 try {
486 VisibilityClient.setAuths(conf, auths, user);
487 } catch (Throwable e) {
488 }
489 return null;
490 }
491 };
492 SUPERUSER.runAs(action);
493 HTable ht = null;
494 try {
495 ht = new HTable(conf, LABELS_TABLE_NAME);
496 Scan scan = new Scan();
497 scan.setAuthorizations(new Authorizations(VisibilityUtils.SYSTEM_LABEL));
498 ResultScanner scanner = ht.getScanner(scan);
499 Result result = null;
500 while ((result = scanner.next()) != null) {
501 Cell label = result.getColumnLatestCell(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
502 Cell userAuth = result.getColumnLatestCell(LABELS_TABLE_FAMILY, user.getBytes());
503 if (Bytes.equals(SECRET.getBytes(), 0, SECRET.getBytes().length, label.getValueArray(),
504 label.getValueOffset(), label.getValueLength())
505 || Bytes.equals(CONFIDENTIAL.getBytes(), 0, CONFIDENTIAL.getBytes().length,
506 label.getValueArray(), label.getValueOffset(), label.getValueLength())) {
507 assertNotNull(userAuth);
508 } else {
509 assertNull(userAuth);
510 }
511 }
512 } finally {
513 if (ht != null) {
514 ht.close();
515 }
516 }
517
518 action = new PrivilegedExceptionAction<Void>() {
519 public Void run() throws Exception {
520 GetAuthsResponse authsResponse = null;
521 try {
522 authsResponse = VisibilityClient.getAuths(conf, user);
523 } catch (Throwable e) {
524 fail("Should not have failed");
525 }
526 List<String> authsList = new ArrayList<String>();
527 for (ByteString authBS : authsResponse.getAuthList()) {
528 authsList.add(Bytes.toString(authBS.toByteArray()));
529 }
530 assertEquals(2, authsList.size());
531 assertTrue(authsList.contains(SECRET));
532 assertTrue(authsList.contains(CONFIDENTIAL));
533 return null;
534 }
535 };
536 SUPERUSER.runAs(action);
537
538
539 action = new PrivilegedExceptionAction<Void>() {
540 public Void run() throws Exception {
541 String[] auths1 = { SECRET, CONFIDENTIAL };
542 GetAuthsResponse authsResponse = null;
543 try {
544 VisibilityClient.setAuths(conf, auths1, user);
545 try {
546 authsResponse = VisibilityClient.getAuths(conf, user);
547 } catch (Throwable e) {
548 fail("Should not have failed");
549 }
550 } catch (Throwable e) {
551 }
552 List<String> authsList = new ArrayList<String>();
553 for (ByteString authBS : authsResponse.getAuthList()) {
554 authsList.add(Bytes.toString(authBS.toByteArray()));
555 }
556 assertEquals(2, authsList.size());
557 assertTrue(authsList.contains(SECRET));
558 assertTrue(authsList.contains(CONFIDENTIAL));
559 return null;
560 }
561 };
562 SUPERUSER.runAs(action);
563 }
564
565 @Test
566 public void testClearUserAuths() throws Throwable {
567 PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
568 public Void run() throws Exception {
569 String[] auths = { SECRET, CONFIDENTIAL, PRIVATE };
570 String user = "testUser";
571 try {
572 VisibilityClient.setAuths(conf, auths, user);
573 } catch (Throwable e) {
574 fail("Should not have failed");
575 }
576
577
578 auths = new String[] { SECRET, PUBLIC, CONFIDENTIAL };
579 VisibilityLabelsResponse response = null;
580 try {
581 response = VisibilityClient.clearAuths(conf, auths, user);
582 } catch (Throwable e) {
583 fail("Should not have failed");
584 }
585 List<RegionActionResult> resultList = response.getResultList();
586 assertEquals(3, resultList.size());
587 assertTrue(resultList.get(0).getException().getValue().isEmpty());
588 assertEquals("org.apache.hadoop.hbase.security.visibility.InvalidLabelException",
589 resultList.get(1).getException().getName());
590 assertTrue(resultList.get(2).getException().getValue().isEmpty());
591 HTable ht = null;
592 try {
593 ht = new HTable(conf, LABELS_TABLE_NAME);
594 ResultScanner scanner = ht.getScanner(new Scan());
595 Result result = null;
596 while ((result = scanner.next()) != null) {
597 Cell label = result.getColumnLatestCell(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
598 Cell userAuth = result.getColumnLatestCell(LABELS_TABLE_FAMILY, user.getBytes());
599 if (Bytes.equals(PRIVATE.getBytes(), 0, PRIVATE.getBytes().length,
600 label.getValueArray(), label.getValueOffset(), label.getValueLength())) {
601 assertNotNull(userAuth);
602 } else {
603 assertNull(userAuth);
604 }
605 }
606 } finally {
607 if (ht != null) {
608 ht.close();
609 }
610 }
611
612 GetAuthsResponse authsResponse = null;
613 try {
614 authsResponse = VisibilityClient.getAuths(conf, user);
615 } catch (Throwable e) {
616 fail("Should not have failed");
617 }
618 List<String> authsList = new ArrayList<String>();
619 for (ByteString authBS : authsResponse.getAuthList()) {
620 authsList.add(Bytes.toString(authBS.toByteArray()));
621 }
622 assertEquals(1, authsList.size());
623 assertTrue(authsList.contains(PRIVATE));
624 return null;
625 }
626 };
627 SUPERUSER.runAs(action);
628 }
629
630 @Test
631 public void testLabelsWithCheckAndPut() throws Throwable {
632 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
633 HTable table = null;
634 try {
635 table = TEST_UTIL.createTable(tableName, fam);
636 byte[] row1 = Bytes.toBytes("row1");
637 Put put = new Put(row1);
638 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
639 put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
640 table.checkAndPut(row1, fam, qual, null, put);
641 byte[] row2 = Bytes.toBytes("row2");
642 put = new Put(row2);
643 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
644 put.setCellVisibility(new CellVisibility(SECRET));
645 table.checkAndPut(row2, fam, qual, null, put);
646
647 Scan scan = new Scan();
648 scan.setAuthorizations(new Authorizations(SECRET));
649 ResultScanner scanner = table.getScanner(scan);
650 Result result = scanner.next();
651 assertTrue(!result.isEmpty());
652 assertTrue(Bytes.equals(row2, result.getRow()));
653 result = scanner.next();
654 assertNull(result);
655 } finally {
656 if (table != null) {
657 table.close();
658 }
659 }
660 }
661
662 @Test
663 public void testLabelsWithIncrement() throws Throwable {
664 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
665 HTable table = null;
666 try {
667 table = TEST_UTIL.createTable(tableName, fam);
668 byte[] row1 = Bytes.toBytes("row1");
669 byte[] val = Bytes.toBytes(1L);
670 Put put = new Put(row1);
671 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, val);
672 put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
673 table.put(put);
674 Get get = new Get(row1);
675 get.setAuthorizations(new Authorizations(SECRET));
676 Result result = table.get(get);
677 assertTrue(result.isEmpty());
678 table.incrementColumnValue(row1, fam, qual, 2L);
679 result = table.get(get);
680 assertTrue(result.isEmpty());
681 Increment increment = new Increment(row1);
682 increment.addColumn(fam, qual, 2L);
683 increment.setCellVisibility(new CellVisibility(SECRET));
684 table.increment(increment);
685 result = table.get(get);
686 assertTrue(!result.isEmpty());
687 } finally {
688 if (table != null) {
689 table.close();
690 }
691 }
692 }
693
694 @Test
695 public void testLabelsWithAppend() throws Throwable {
696 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
697 HTable table = null;
698 try {
699 table = TEST_UTIL.createTable(tableName, fam);
700 byte[] row1 = Bytes.toBytes("row1");
701 byte[] val = Bytes.toBytes("a");
702 Put put = new Put(row1);
703 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, val);
704 put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
705 table.put(put);
706 Get get = new Get(row1);
707 get.setAuthorizations(new Authorizations(SECRET));
708 Result result = table.get(get);
709 assertTrue(result.isEmpty());
710 Append append = new Append(row1);
711 append.add(fam, qual, Bytes.toBytes("b"));
712 table.append(append);
713 result = table.get(get);
714 assertTrue(result.isEmpty());
715 append = new Append(row1);
716 append.add(fam, qual, Bytes.toBytes("c"));
717 append.setCellVisibility(new CellVisibility(SECRET));
718 table.append(append);
719 result = table.get(get);
720 assertTrue(!result.isEmpty());
721 } finally {
722 if (table != null) {
723 table.close();
724 }
725 }
726 }
727
728 @Test
729 public void testUserShouldNotDoDDLOpOnLabelsTable() throws Exception {
730 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
731 try {
732 admin.disableTable(LABELS_TABLE_NAME);
733 fail("Lables table should not get disabled by user.");
734 } catch (Exception e) {
735 }
736 try {
737 admin.deleteTable(LABELS_TABLE_NAME);
738 fail("Lables table should not get disabled by user.");
739 } catch (Exception e) {
740 }
741 try {
742 HColumnDescriptor hcd = new HColumnDescriptor("testFamily");
743 admin.addColumn(LABELS_TABLE_NAME, hcd);
744 fail("Lables table should not get altered by user.");
745 } catch (Exception e) {
746 }
747 try {
748 admin.deleteColumn(LABELS_TABLE_NAME, VisibilityConstants.LABELS_TABLE_FAMILY);
749 fail("Lables table should not get altered by user.");
750 } catch (Exception e) {
751 }
752 try {
753 HColumnDescriptor hcd = new HColumnDescriptor(VisibilityConstants.LABELS_TABLE_FAMILY);
754 hcd.setBloomFilterType(BloomType.ROWCOL);
755 admin.modifyColumn(LABELS_TABLE_NAME, hcd);
756 fail("Lables table should not get altered by user.");
757 } catch (Exception e) {
758 }
759 try {
760 HTableDescriptor htd = new HTableDescriptor(LABELS_TABLE_NAME);
761 htd.addFamily(new HColumnDescriptor("f1"));
762 htd.addFamily(new HColumnDescriptor("f2"));
763 admin.modifyTable(LABELS_TABLE_NAME, htd);
764 fail("Lables table should not get altered by user.");
765 } catch (Exception e) {
766 }
767 }
768
769 @Test
770 public void testMultipleVersions() throws Exception {
771 final byte[] r1 = Bytes.toBytes("row1");
772 final byte[] r2 = Bytes.toBytes("row2");
773 final byte[] v1 = Bytes.toBytes("100");
774 final byte[] v2 = Bytes.toBytes("101");
775 final byte[] fam2 = Bytes.toBytes("info2");
776 final byte[] qual2 = Bytes.toBytes("qual2");
777 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
778 HTableDescriptor desc = new HTableDescriptor(tableName);
779 HColumnDescriptor col = new HColumnDescriptor(fam);
780 desc.addFamily(col);
781 col = new HColumnDescriptor(fam2);
782 col.setMaxVersions(5);
783 desc.addFamily(col);
784 TEST_UTIL.getHBaseAdmin().createTable(desc);
785 HTable table = null;
786 try {
787 table = new HTable(TEST_UTIL.getConfiguration(), tableName);
788 Put put = new Put(r1);
789 put.add(fam, qual, 3l, v1);
790 put.add(fam, qual2, 3l, v1);
791 put.add(fam2, qual, 3l, v1);
792 put.add(fam2, qual2, 3l, v1);
793 put.setCellVisibility(new CellVisibility(SECRET));
794 table.put(put);
795 put = new Put(r1);
796 put.add(fam, qual, 4l, v2);
797 put.add(fam, qual2, 4l, v2);
798 put.add(fam2, qual, 4l, v2);
799 put.add(fam2, qual2, 4l, v2);
800 put.setCellVisibility(new CellVisibility(PRIVATE));
801 table.put(put);
802
803 put = new Put(r2);
804 put.add(fam, qual, 3l, v1);
805 put.add(fam, qual2, 3l, v1);
806 put.add(fam2, qual, 3l, v1);
807 put.add(fam2, qual2, 3l, v1);
808 put.setCellVisibility(new CellVisibility(SECRET));
809 table.put(put);
810 put = new Put(r2);
811 put.add(fam, qual, 4l, v2);
812 put.add(fam, qual2, 4l, v2);
813 put.add(fam2, qual, 4l, v2);
814 put.add(fam2, qual2, 4l, v2);
815 put.setCellVisibility(new CellVisibility(SECRET));
816 table.put(put);
817
818 Scan s = new Scan();
819 s.setMaxVersions(1);
820 s.setAuthorizations(new Authorizations(SECRET));
821 ResultScanner scanner = table.getScanner(s);
822 Result result = scanner.next();
823 assertTrue(Bytes.equals(r1, result.getRow()));
824
825
826
827 assertNull(result.getColumnLatestCell(fam, qual));
828 assertNull(result.getColumnLatestCell(fam, qual2));
829
830
831
832
833 Cell cell = result.getColumnLatestCell(fam2, qual);
834 assertNotNull(cell);
835 assertTrue(Bytes.equals(v1, 0, v1.length, cell.getValueArray(), cell.getValueOffset(),
836 cell.getValueLength()));
837 cell = result.getColumnLatestCell(fam2, qual2);
838 assertNotNull(cell);
839 assertTrue(Bytes.equals(v1, 0, v1.length, cell.getValueArray(), cell.getValueOffset(),
840 cell.getValueLength()));
841
842 result = scanner.next();
843 assertTrue(Bytes.equals(r2, result.getRow()));
844 cell = result.getColumnLatestCell(fam, qual);
845 assertNotNull(cell);
846 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
847 cell.getValueLength()));
848 cell = result.getColumnLatestCell(fam, qual2);
849 assertNotNull(cell);
850 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
851 cell.getValueLength()));
852 cell = result.getColumnLatestCell(fam2, qual);
853 assertNotNull(cell);
854 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
855 cell.getValueLength()));
856 cell = result.getColumnLatestCell(fam2, qual2);
857 assertNotNull(cell);
858 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
859 cell.getValueLength()));
860 } finally {
861 if (table != null) {
862 table.close();
863 }
864 }
865 }
866
867 @Test
868 public void testMutateRow() throws Exception {
869 final byte[] qual2 = Bytes.toBytes("qual2");
870 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
871 HTableDescriptor desc = new HTableDescriptor(tableName);
872 HColumnDescriptor col = new HColumnDescriptor(fam);
873 desc.addFamily(col);
874 TEST_UTIL.getHBaseAdmin().createTable(desc);
875 HTable table = new HTable(TEST_UTIL.getConfiguration(), tableName);
876 try {
877 Put p1 = new Put(row1);
878 p1.add(fam, qual, value);
879 p1.setCellVisibility(new CellVisibility(CONFIDENTIAL));
880
881 Put p2 = new Put(row1);
882 p2.add(fam, qual2, value);
883 p2.setCellVisibility(new CellVisibility(SECRET));
884
885 RowMutations rm = new RowMutations(row1);
886 rm.add(p1);
887 rm.add(p2);
888
889 table.mutateRow(rm);
890
891 Get get = new Get(row1);
892 get.setAuthorizations(new Authorizations(CONFIDENTIAL));
893 Result result = table.get(get);
894 assertTrue(result.containsColumn(fam, qual));
895 assertFalse(result.containsColumn(fam, qual2));
896
897 get.setAuthorizations(new Authorizations(SECRET));
898 result = table.get(get);
899 assertFalse(result.containsColumn(fam, qual));
900 assertTrue(result.containsColumn(fam, qual2));
901 } finally {
902 table.close();
903 }
904 }
905
906 private static HTable createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)
907 throws Exception {
908 HTable table = null;
909 try {
910 table = TEST_UTIL.createTable(tableName, fam);
911 int i = 1;
912 List<Put> puts = new ArrayList<Put>();
913 for (String labelExp : labelExps) {
914 Put put = new Put(Bytes.toBytes("row" + i));
915 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
916 put.setCellVisibility(new CellVisibility(labelExp));
917 puts.add(put);
918 i++;
919 }
920 table.put(puts);
921 } finally {
922 if (table != null) {
923 table.close();
924 }
925 }
926 return table;
927 }
928
929 public static void addLabels() throws Exception {
930 PrivilegedExceptionAction<VisibilityLabelsResponse> action =
931 new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
932 public VisibilityLabelsResponse run() throws Exception {
933 String[] labels = { SECRET, TOPSECRET, CONFIDENTIAL, PUBLIC, PRIVATE };
934 try {
935 VisibilityClient.addLabels(conf, labels);
936 } catch (Throwable t) {
937 throw new IOException(t);
938 }
939 return null;
940 }
941 };
942 SUPERUSER.runAs(action);
943 }
944 }