View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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.assertNotNull;
25  import static org.junit.Assert.assertNull;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  
29  import java.io.IOException;
30  import java.security.PrivilegedExceptionAction;
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  import org.apache.hadoop.conf.Configuration;
35  import org.apache.hadoop.hbase.Cell;
36  import org.apache.hadoop.hbase.CellScanner;
37  import org.apache.hadoop.hbase.HBaseTestingUtility;
38  import org.apache.hadoop.hbase.HConstants;
39  import org.apache.hadoop.hbase.MediumTests;
40  import org.apache.hadoop.hbase.TableName;
41  import org.apache.hadoop.hbase.client.Append;
42  import org.apache.hadoop.hbase.client.Get;
43  import org.apache.hadoop.hbase.client.HTable;
44  import org.apache.hadoop.hbase.client.Increment;
45  import org.apache.hadoop.hbase.client.Put;
46  import org.apache.hadoop.hbase.client.Result;
47  import org.apache.hadoop.hbase.client.ResultScanner;
48  import org.apache.hadoop.hbase.client.Scan;
49  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionActionResult;
50  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
51  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
52  import org.apache.hadoop.hbase.regionserver.HRegion;
53  import org.apache.hadoop.hbase.regionserver.HRegionServer;
54  import org.apache.hadoop.hbase.security.User;
55  import org.apache.hadoop.hbase.util.Bytes;
56  import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
57  import org.junit.After;
58  import org.junit.AfterClass;
59  import org.junit.Assert;
60  import org.junit.BeforeClass;
61  import org.junit.Rule;
62  import org.junit.Test;
63  import org.junit.experimental.categories.Category;
64  import org.junit.rules.TestName;
65  
66  import com.google.protobuf.ByteString;
67  
68  /**
69   * Test class that tests the visibility labels
70   */
71  @Category(MediumTests.class)
72  public class TestVisibilityLabels {
73  
74    private static final String TOPSECRET = "topsecret";
75    private static final String PUBLIC = "public";
76    private static final String PRIVATE = "private";
77    private static final String CONFIDENTIAL = "confidential";
78    private static final String SECRET = "secret";
79    public static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
80    private static final byte[] row1 = Bytes.toBytes("row1");
81    private static final byte[] row2 = Bytes.toBytes("row2");
82    private static final byte[] row3 = Bytes.toBytes("row3");
83    private static final byte[] row4 = Bytes.toBytes("row4");
84    private final static byte[] fam = Bytes.toBytes("info");
85    private final static byte[] qual = Bytes.toBytes("qual");
86    private final static byte[] value = Bytes.toBytes("value");
87    public static Configuration conf;
88  
89    private volatile boolean killedRS = false;
90    @Rule 
91    public final TestName TEST_NAME = new TestName();
92    public static User SUPERUSER;
93  
94    @BeforeClass
95    public static void setupBeforeClass() throws Exception {
96      // setup configuration
97      conf = TEST_UTIL.getConfiguration();
98      conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
99      conf.setInt("hfile.format.version", 3);
100     conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
101     conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
102     conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
103         ScanLabelGenerator.class);
104     conf.set("hbase.superuser", "admin");
105     TEST_UTIL.startMiniCluster(2);
106     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
107 
108     // Wait for the labels table to become available
109     TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
110     addLabels();
111   }
112 
113   @AfterClass
114   public static void tearDownAfterClass() throws Exception {
115     TEST_UTIL.shutdownMiniCluster();
116   }
117 
118   @After
119   public void tearDown() throws Exception {
120     killedRS = false;
121   }
122 
123   @Test
124   public void testSimpleVisibilityLabels() throws Exception {
125     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
126     HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "|" + CONFIDENTIAL,
127         PRIVATE + "|" + CONFIDENTIAL);
128     try {
129       Scan s = new Scan();
130       s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL, PRIVATE));
131       ResultScanner scanner = table.getScanner(s);
132       Result[] next = scanner.next(3);
133 
134       assertTrue(next.length == 2);
135       CellScanner cellScanner = next[0].cellScanner();
136       cellScanner.advance();
137       Cell current = cellScanner.current();
138       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
139           current.getRowLength(), row1, 0, row1.length));
140       cellScanner = next[1].cellScanner();
141       cellScanner.advance();
142       current = cellScanner.current();
143       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
144           current.getRowLength(), row2, 0, row2.length));
145     } finally {
146       if (table != null) {
147         table.close();
148       }
149     }
150   }
151 
152   @Test
153   public void testVisibilityLabelsWithComplexLabels() throws Exception {
154     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
155     HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
156         + ")" + "&" + "!" + TOPSECRET, "(" + PRIVATE + "&" + CONFIDENTIAL + "&" + SECRET + ")", "("
157         + PRIVATE + "&" + CONFIDENTIAL + "&" + SECRET + ")", "(" + PRIVATE + "&" + CONFIDENTIAL
158         + "&" + SECRET + ")");
159     try {
160       Scan s = new Scan();
161       s.setAuthorizations(new Authorizations(TOPSECRET, CONFIDENTIAL, PRIVATE, PUBLIC, SECRET));
162       ResultScanner scanner = table.getScanner(s);
163       Result[] next = scanner.next(4);
164       assertEquals(3, next.length);
165       CellScanner cellScanner = next[0].cellScanner();
166       cellScanner.advance();
167       Cell current = cellScanner.current();
168       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
169           current.getRowLength(), row2, 0, row2.length));
170       cellScanner = next[1].cellScanner();
171       cellScanner.advance();
172       current = cellScanner.current();
173       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
174           current.getRowLength(), row3, 0, row3.length));
175       cellScanner = next[2].cellScanner();
176       cellScanner.advance();
177       current = cellScanner.current();
178       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
179           current.getRowLength(), row4, 0, row4.length));
180     } finally {
181       if (table != null) {
182         table.close();
183       }
184     }
185   }
186 
187   @Test
188   public void testVisibilityLabelsThatDoesNotPassTheCriteria() throws Exception {
189     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
190     HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
191         + ")", PRIVATE);
192     try {
193       Scan s = new Scan();
194       s.setAuthorizations(new Authorizations(PUBLIC));
195       ResultScanner scanner = table.getScanner(s);
196       Result[] next = scanner.next(3);
197       assertTrue(next.length == 0);
198     } finally {
199       if (table != null) {
200         table.close();
201       }
202     }
203   }
204 
205   @Test
206   public void testVisibilityLabelsInPutsThatDoesNotMatchAnyDefinedLabels() throws Exception {
207     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
208     try {
209       createTableAndWriteDataWithLabels(tableName, "SAMPLE_LABEL", "TEST");
210       fail("Should have failed with failed sanity check exception");
211     } catch (Exception e) {
212     }
213   }
214 
215   @Test
216   public void testVisibilityLabelsInScanThatDoesNotMatchAnyDefinedLabels() throws Exception {
217     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
218     HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
219         + ")", PRIVATE);
220     try {
221       Scan s = new Scan();
222       s.setAuthorizations(new Authorizations("SAMPLE"));
223       ResultScanner scanner = table.getScanner(s);
224       Result[] next = scanner.next(3);
225       assertTrue(next.length == 0);
226     } finally {
227       if (table != null) {
228         table.close();
229       }
230     }
231   }
232 
233   @Test
234   public void testVisibilityLabelsWithGet() throws Exception {
235     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
236     HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL + "&!"
237         + PRIVATE, SECRET + "&" + CONFIDENTIAL + "&" + PRIVATE);
238     try {
239       Get get = new Get(row1);
240       get.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
241       Result result = table.get(get);
242       assertTrue(!result.isEmpty());
243       Cell cell = result.getColumnLatestCell(fam, qual);
244       assertTrue(Bytes.equals(value, 0, value.length, cell.getValueArray(), cell.getValueOffset(),
245           cell.getValueLength()));
246     } finally {
247       if (table != null) {
248         table.close();
249       }
250     }
251   }
252 
253   @Test
254   public void testVisibilityLabelsOnKillingOfRSContainingLabelsTable() throws Exception {
255     List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
256         .getRegionServerThreads();
257     int liveRS = 0;
258     for (RegionServerThread rsThreads : regionServerThreads) {
259       if (!rsThreads.getRegionServer().isAborted()) {
260         liveRS++;
261       }
262     }
263     if (liveRS == 1) {
264       TEST_UTIL.getHBaseCluster().startRegionServer();
265     }
266     Thread t1 = new Thread() {
267       public void run() {
268         List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
269             .getRegionServerThreads();
270         for (RegionServerThread rsThread : regionServerThreads) {
271           List<HRegion> onlineRegions = rsThread.getRegionServer().getOnlineRegions(
272               LABELS_TABLE_NAME);
273           if (onlineRegions.size() > 0) {
274             rsThread.getRegionServer().abort("Aborting ");
275             killedRS = true;
276             break;
277           }
278         }
279       }
280 
281     };
282     t1.start();
283     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
284     Thread t = new Thread() {
285       public void run() {
286         try {
287           while (!killedRS) {
288             Thread.sleep(1);
289           }
290           createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL + ")",
291               PRIVATE);
292         } catch (Exception e) {
293         }
294       }
295     };
296     t.start();
297     regionServerThreads = TEST_UTIL.getHBaseCluster().getRegionServerThreads();
298     while (!killedRS) {
299       Thread.sleep(10);
300     }
301     regionServerThreads = TEST_UTIL.getHBaseCluster().getRegionServerThreads();
302     for (RegionServerThread rsThread : regionServerThreads) {
303       while (true) {
304         if (!rsThread.getRegionServer().isAborted()) {
305           List<HRegion> onlineRegions = rsThread.getRegionServer().getOnlineRegions(
306               LABELS_TABLE_NAME);
307           if (onlineRegions.size() > 0) {
308             break;
309           } else {
310             Thread.sleep(10);
311           }
312         } else {
313           break;
314         }
315       }
316     }
317     TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
318     t.join();
319     HTable table = null;
320     try {
321       table = new HTable(TEST_UTIL.getConfiguration(), tableName);
322       Scan s = new Scan();
323       s.setAuthorizations(new Authorizations(SECRET));
324       ResultScanner scanner = table.getScanner(s);
325       Result[] next = scanner.next(3);
326       assertTrue(next.length == 1);
327     } finally {
328       if (table != null) {
329         table.close();
330       }
331     }
332   }
333 
334   @Test(timeout = 60 * 1000)
335   public void testVisibilityLabelsOnRSRestart() throws Exception {
336     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
337     HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
338         + ")", PRIVATE);
339     List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
340         .getRegionServerThreads();
341     for (RegionServerThread rsThread : regionServerThreads) {
342       rsThread.getRegionServer().abort("Aborting ");
343     }
344     // Start one new RS
345     RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer();
346     waitForLabelsRegionAvailability(rs.getRegionServer());
347     try {
348       Scan s = new Scan();
349       s.setAuthorizations(new Authorizations(SECRET));
350       ResultScanner scanner = table.getScanner(s);
351       Result[] next = scanner.next(3);
352       assertTrue(next.length == 1);
353     } finally {
354       if (table != null) {
355         table.close();
356       }
357     }
358   }
359 
360   @Test(timeout = 60 * 1000)
361   public void testAddVisibilityLabelsOnRSRestart() throws Exception {
362     List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
363         .getRegionServerThreads();
364     for (RegionServerThread rsThread : regionServerThreads) {
365       rsThread.getRegionServer().abort("Aborting ");
366     }
367     // Start one new RS
368     RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer();
369     waitForLabelsRegionAvailability(rs.getRegionServer());
370     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
371         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
372       public VisibilityLabelsResponse run() throws Exception {
373         String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, "ABC", "XYZ" };
374         try {
375           VisibilityClient.addLabels(conf, labels);
376         } catch (Throwable t) {
377           throw new IOException(t);
378         }
379         return null;
380       }
381     };
382     SUPERUSER.runAs(action);
383     // Scan the visibility label
384     Scan s = new Scan();
385     s.setAuthorizations(new Authorizations(VisibilityUtils.SYSTEM_LABEL));
386     HTable ht = new HTable(conf, LABELS_TABLE_NAME.getName());
387     int i = 0;
388     try {
389       ResultScanner scanner = ht.getScanner(s);
390       while (true) {
391         Result next = scanner.next();
392         if (next == null) {
393           break;
394         }
395         i++;
396       }
397     } finally {
398       if (ht != null) {
399         ht.close();
400       }
401     }
402     // One label is the "system" label.
403     Assert.assertEquals("The count should be 8", 8, i);
404   }
405 
406   private void waitForLabelsRegionAvailability(HRegionServer regionServer) {
407     while (!regionServer.isOnline()) {
408       try {
409         Thread.sleep(10);
410       } catch (InterruptedException e) {
411       }
412     }
413     while (regionServer.getOnlineRegions(LABELS_TABLE_NAME).isEmpty()) {
414       try {
415         Thread.sleep(10);
416       } catch (InterruptedException e) {
417       }
418     }
419     HRegion labelsTableRegion = regionServer.getOnlineRegions(LABELS_TABLE_NAME).get(0);
420     while (labelsTableRegion.isRecovering()) {
421       try {
422         Thread.sleep(10);
423       } catch (InterruptedException e) {
424       }
425     }
426   }
427 
428   @Test
429   public void testVisibilityLabelsInGetThatDoesNotMatchAnyDefinedLabels() throws Exception {
430     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
431     HTable table = createTableAndWriteDataWithLabels(tableName, "(" + SECRET + "|" + CONFIDENTIAL
432         + ")", PRIVATE);
433     try {
434       Get get = new Get(row1);
435       get.setAuthorizations(new Authorizations("SAMPLE"));
436       Result result = table.get(get);
437       assertTrue(result.isEmpty());
438     } finally {
439       if (table != null) {
440         table.close();
441       }
442     }
443   }
444 
445   @Test
446   public void testAddLabels() throws Throwable {
447     PrivilegedExceptionAction<VisibilityLabelsResponse> action = 
448         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
449       public VisibilityLabelsResponse run() throws Exception {
450         String[] labels = { "L1", SECRET, "L2", "invalid~", "L3" };
451         VisibilityLabelsResponse response = null;
452         try {
453           response = VisibilityClient.addLabels(conf, labels);
454         } catch (Throwable e) {
455           fail("Should not have thrown exception");
456         }
457         List<RegionActionResult> resultList = response.getResultList();
458         assertEquals(5, resultList.size());
459         assertTrue(resultList.get(0).getException().getValue().isEmpty());
460         assertEquals("org.apache.hadoop.hbase.security.visibility.LabelAlreadyExistsException",
461             resultList.get(1).getException().getName());
462         assertTrue(resultList.get(2).getException().getValue().isEmpty());
463         assertEquals("org.apache.hadoop.hbase.security.visibility.InvalidLabelException",
464             resultList.get(3).getException().getName());
465         assertTrue(resultList.get(4).getException().getValue().isEmpty());
466         return null;
467       }
468     };
469     SUPERUSER.runAs(action);
470   }
471 
472   @Test
473   public void testSetAndGetUserAuths() throws Throwable {
474     final String user = "user1";
475     PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
476       public Void run() throws Exception {
477         String[] auths = { SECRET, CONFIDENTIAL };
478         try {
479           VisibilityClient.setAuths(conf, auths, user);
480         } catch (Throwable e) {
481         }
482         return null;
483       }
484     };
485     SUPERUSER.runAs(action);
486     HTable ht = null;
487     try {
488       ht = new HTable(conf, LABELS_TABLE_NAME);
489       Scan scan = new Scan();
490       scan.setAuthorizations(new Authorizations(VisibilityUtils.SYSTEM_LABEL));
491       ResultScanner scanner = ht.getScanner(scan);
492       Result result = null;
493       while ((result = scanner.next()) != null) {
494         Cell label = result.getColumnLatestCell(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
495         Cell userAuth = result.getColumnLatestCell(LABELS_TABLE_FAMILY, user.getBytes());
496         if (Bytes.equals(SECRET.getBytes(), 0, SECRET.getBytes().length, label.getValueArray(),
497             label.getValueOffset(), label.getValueLength())
498             || Bytes.equals(CONFIDENTIAL.getBytes(), 0, CONFIDENTIAL.getBytes().length,
499                 label.getValueArray(), label.getValueOffset(), label.getValueLength())) {
500           assertNotNull(userAuth);
501         } else {
502           assertNull(userAuth);
503         }
504       }
505     } finally {
506       if (ht != null) {
507         ht.close();
508       }
509     }
510 
511     action = new PrivilegedExceptionAction<Void>() {
512       public Void run() throws Exception {
513         GetAuthsResponse authsResponse = null;
514         try {
515           authsResponse = VisibilityClient.getAuths(conf, user);
516         } catch (Throwable e) {
517           fail("Should not have failed");
518         }
519         List<String> authsList = new ArrayList<String>();
520         for (ByteString authBS : authsResponse.getAuthList()) {
521           authsList.add(Bytes.toString(authBS.toByteArray()));
522         }
523         assertEquals(2, authsList.size());
524         assertTrue(authsList.contains(SECRET));
525         assertTrue(authsList.contains(CONFIDENTIAL));
526         return null;
527       }
528     };
529     SUPERUSER.runAs(action);
530 
531     // Try doing setAuths once again and there should not be any duplicates
532     action = new PrivilegedExceptionAction<Void>() {
533       public Void run() throws Exception {
534         String[] auths1 = { SECRET, CONFIDENTIAL };
535         GetAuthsResponse authsResponse = null;
536         try {
537           VisibilityClient.setAuths(conf, auths1, user);
538           try {
539             authsResponse = VisibilityClient.getAuths(conf, user);
540           } catch (Throwable e) {
541             fail("Should not have failed");
542           }
543         } catch (Throwable e) {
544         }
545         List<String> authsList = new ArrayList<String>();
546         for (ByteString authBS : authsResponse.getAuthList()) {
547           authsList.add(Bytes.toString(authBS.toByteArray()));
548         }
549         assertEquals(2, authsList.size());
550         assertTrue(authsList.contains(SECRET));
551         assertTrue(authsList.contains(CONFIDENTIAL));
552         return null;
553       }
554     };
555     SUPERUSER.runAs(action);
556   }
557 
558   @Test
559   public void testClearUserAuths() throws Throwable {
560     PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
561       public Void run() throws Exception {
562         String[] auths = { SECRET, CONFIDENTIAL, PRIVATE };
563         String user = "testUser";
564         try {
565           VisibilityClient.setAuths(conf, auths, user);
566         } catch (Throwable e) {
567           fail("Should not have failed");
568         }
569         // Removing the auths for SECRET and CONFIDENTIAL for the user.
570         // Passing a non existing auth also.
571         auths = new String[] { SECRET, PUBLIC, CONFIDENTIAL };
572         VisibilityLabelsResponse response = null;
573         try {
574           response = VisibilityClient.clearAuths(conf, auths, user);
575         } catch (Throwable e) {
576           fail("Should not have failed");
577         }
578         List<RegionActionResult> resultList = response.getResultList();
579         assertEquals(3, resultList.size());
580         assertTrue(resultList.get(0).getException().getValue().isEmpty());
581         assertEquals("org.apache.hadoop.hbase.security.visibility.InvalidLabelException",
582             resultList.get(1).getException().getName());
583         assertTrue(resultList.get(2).getException().getValue().isEmpty());
584         HTable ht = null;
585         try {
586           ht = new HTable(conf, LABELS_TABLE_NAME);
587           ResultScanner scanner = ht.getScanner(new Scan());
588           Result result = null;
589           while ((result = scanner.next()) != null) {
590             Cell label = result.getColumnLatestCell(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
591             Cell userAuth = result.getColumnLatestCell(LABELS_TABLE_FAMILY, user.getBytes());
592             if (Bytes.equals(PRIVATE.getBytes(), 0, PRIVATE.getBytes().length,
593                 label.getValueArray(), label.getValueOffset(), label.getValueLength())) {
594               assertNotNull(userAuth);
595             } else {
596               assertNull(userAuth);
597             }
598           }
599         } finally {
600           if (ht != null) {
601             ht.close();
602           }
603         }
604 
605         GetAuthsResponse authsResponse = null;
606         try {
607           authsResponse = VisibilityClient.getAuths(conf, user);
608         } catch (Throwable e) {
609           fail("Should not have failed");
610         }
611         List<String> authsList = new ArrayList<String>();
612         for (ByteString authBS : authsResponse.getAuthList()) {
613           authsList.add(Bytes.toString(authBS.toByteArray()));
614         }
615         assertEquals(1, authsList.size());
616         assertTrue(authsList.contains(PRIVATE));
617         return null;
618       }
619     };
620     SUPERUSER.runAs(action);
621   }
622 
623   @Test
624   public void testLabelsWithCheckAndPut() throws Throwable {
625     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
626     HTable table = null;
627     try {
628       table = TEST_UTIL.createTable(tableName, fam);
629       byte[] row1 = Bytes.toBytes("row1");
630       Put put = new Put(row1);
631       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
632       put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
633       table.checkAndPut(row1, fam, qual, null, put);
634       byte[] row2 = Bytes.toBytes("row2");
635       put = new Put(row2);
636       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
637       put.setCellVisibility(new CellVisibility(SECRET));
638       table.checkAndPut(row2, fam, qual, null, put);
639       
640       Scan scan = new Scan();
641       scan.setAuthorizations(new Authorizations(SECRET));
642       ResultScanner scanner = table.getScanner(scan);
643       Result result = scanner.next();
644       assertTrue(!result.isEmpty());
645       assertTrue(Bytes.equals(row2, result.getRow()));
646       result = scanner.next();
647       assertNull(result);
648     } finally {
649       if (table != null) {
650         table.close();
651       }
652     }
653   }
654 
655   @Test
656   public void testLabelsWithIncrement() throws Throwable {
657     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
658     HTable table = null;
659     try {
660       table = TEST_UTIL.createTable(tableName, fam);
661       byte[] row1 = Bytes.toBytes("row1");
662       byte[] val = Bytes.toBytes(1L);
663       Put put = new Put(row1);
664       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, val);
665       put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
666       table.put(put);
667       Get get = new Get(row1);
668       get.setAuthorizations(new Authorizations(SECRET));
669       Result result = table.get(get);
670       assertTrue(result.isEmpty());
671       table.incrementColumnValue(row1, fam, qual, 2L);
672       result = table.get(get);
673       assertTrue(result.isEmpty());
674       Increment increment = new Increment(row1);
675       increment.addColumn(fam, qual, 2L);
676       increment.setCellVisibility(new CellVisibility(SECRET));
677       table.increment(increment);
678       result = table.get(get);
679       assertTrue(!result.isEmpty());
680     } finally {
681       if (table != null) {
682         table.close();
683       }
684     }
685   }
686 
687   @Test
688   public void testLabelsWithAppend() throws Throwable {
689     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
690     HTable table = null;
691     try {
692       table = TEST_UTIL.createTable(tableName, fam);
693       byte[] row1 = Bytes.toBytes("row1");
694       byte[] val = Bytes.toBytes("a");
695       Put put = new Put(row1);
696       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, val);
697       put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
698       table.put(put);
699       Get get = new Get(row1);
700       get.setAuthorizations(new Authorizations(SECRET));
701       Result result = table.get(get);
702       assertTrue(result.isEmpty());
703       Append append = new Append(row1);
704       append.add(fam, qual, Bytes.toBytes("b"));
705       table.append(append);
706       result = table.get(get);
707       assertTrue(result.isEmpty());
708       append = new Append(row1);
709       append.add(fam, qual, Bytes.toBytes("c"));
710       append.setCellVisibility(new CellVisibility(SECRET));
711       table.append(append);
712       result = table.get(get);
713       assertTrue(!result.isEmpty());
714     } finally {
715       if (table != null) {
716         table.close();
717       }
718     }
719   }
720 
721   private static HTable createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)
722       throws Exception {
723     HTable table = null;
724     try {
725       table = TEST_UTIL.createTable(tableName, fam);
726       int i = 1;
727       List<Put> puts = new ArrayList<Put>();
728       for (String labelExp : labelExps) {
729         Put put = new Put(Bytes.toBytes("row" + i));
730         put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
731         put.setCellVisibility(new CellVisibility(labelExp));
732         puts.add(put);
733         i++;
734       }
735       table.put(puts);
736     } finally {
737       if (table != null) {
738         table.close();
739       }
740     }
741     return table;
742   }
743 
744   public static void addLabels() throws Exception {
745     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
746         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
747       public VisibilityLabelsResponse run() throws Exception {
748         String[] labels = { SECRET, TOPSECRET, CONFIDENTIAL, PUBLIC, PRIVATE };
749         try {
750           VisibilityClient.addLabels(conf, labels);
751         } catch (Throwable t) {
752           throw new IOException(t);
753         }
754         return null;
755       }
756     };
757     SUPERUSER.runAs(action);
758   }
759 }