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