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 List<String> authsList = new ArrayList<String>();
487 for (ByteString authBS : authsResponse.getAuthList()) {
488 authsList.add(Bytes.toString(authBS.toByteArray()));
489 }
490 assertEquals(2, authsList.size());
491 assertTrue(authsList.contains(SECRET));
492 assertTrue(authsList.contains(CONFIDENTIAL));
493 return null;
494 }
495 };
496 SUPERUSER.runAs(action);
497 }
498
499 protected List<String> extractAuths(String user, List<Result> results) {
500 List<String> auths = new ArrayList<String>();
501 for (Result result : results) {
502 Cell labelCell = result.getColumnLatestCell(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
503 Cell userAuthCell = result.getColumnLatestCell(LABELS_TABLE_FAMILY, user.getBytes());
504 if (userAuthCell != null) {
505 auths.add(Bytes.toString(labelCell.getValueArray(), labelCell.getValueOffset(),
506 labelCell.getValueLength()));
507 }
508 }
509 return auths;
510 }
511
512 @Test
513 public void testClearUserAuths() throws Throwable {
514 PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
515 public Void run() throws Exception {
516 String[] auths = { SECRET, CONFIDENTIAL, PRIVATE };
517 String user = "testUser";
518 try (Connection conn = ConnectionFactory.createConnection(conf)) {
519 VisibilityClient.setAuths(conn, auths, user);
520 } catch (Throwable e) {
521 fail("Should not have failed");
522 }
523
524
525 auths = new String[] { SECRET, PUBLIC, CONFIDENTIAL };
526 VisibilityLabelsResponse response = null;
527 try (Connection conn = ConnectionFactory.createConnection(conf)) {
528 response = VisibilityClient.clearAuths(conn, auths, user);
529 } catch (Throwable e) {
530 fail("Should not have failed");
531 }
532 List<RegionActionResult> resultList = response.getResultList();
533 assertEquals(3, resultList.size());
534 assertTrue(resultList.get(0).getException().getValue().isEmpty());
535 assertEquals("org.apache.hadoop.hbase.DoNotRetryIOException",
536 resultList.get(1).getException().getName());
537 assertTrue(Bytes.toString(resultList.get(1).getException().getValue().toByteArray())
538 .contains(
539 "org.apache.hadoop.hbase.security.visibility.InvalidLabelException: "
540 + "Label 'public' is not set for the user testUser"));
541 assertTrue(resultList.get(2).getException().getValue().isEmpty());
542 try (Connection connection = ConnectionFactory.createConnection(conf);
543 Table ht = connection.getTable(LABELS_TABLE_NAME)) {
544 ResultScanner scanner = ht.getScanner(new Scan());
545 Result result = null;
546 List<Result> results = new ArrayList<Result>();
547 while ((result = scanner.next()) != null) {
548 results.add(result);
549 }
550 List<String> curAuths = extractAuths(user, results);
551 assertTrue(curAuths.contains(PRIVATE));
552 assertEquals(1, curAuths.size());
553 }
554
555 GetAuthsResponse authsResponse = null;
556 try (Connection conn = ConnectionFactory.createConnection(conf)) {
557 authsResponse = VisibilityClient.getAuths(conn, user);
558 } catch (Throwable e) {
559 fail("Should not have failed");
560 }
561 List<String> authsList = new ArrayList<String>();
562 for (ByteString authBS : authsResponse.getAuthList()) {
563 authsList.add(Bytes.toString(authBS.toByteArray()));
564 }
565 assertEquals(1, authsList.size());
566 assertTrue(authsList.contains(PRIVATE));
567 return null;
568 }
569 };
570 SUPERUSER.runAs(action);
571 }
572
573 @Test
574 public void testLabelsWithCheckAndPut() throws Throwable {
575 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
576 try (Table table = TEST_UTIL.createTable(tableName, fam)) {
577 byte[] row1 = Bytes.toBytes("row1");
578 Put put = new Put(row1);
579 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
580 put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
581 table.checkAndPut(row1, fam, qual, null, put);
582 byte[] row2 = Bytes.toBytes("row2");
583 put = new Put(row2);
584 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
585 put.setCellVisibility(new CellVisibility(SECRET));
586 table.checkAndPut(row2, fam, qual, null, put);
587
588 Scan scan = new Scan();
589 scan.setAuthorizations(new Authorizations(SECRET));
590 ResultScanner scanner = table.getScanner(scan);
591 Result result = scanner.next();
592 assertTrue(!result.isEmpty());
593 assertTrue(Bytes.equals(row2, result.getRow()));
594 result = scanner.next();
595 assertNull(result);
596 }
597 }
598
599 @Test
600 public void testLabelsWithIncrement() throws Throwable {
601 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
602 try (Table table = TEST_UTIL.createTable(tableName, fam)) {
603 byte[] row1 = Bytes.toBytes("row1");
604 byte[] val = Bytes.toBytes(1L);
605 Put put = new Put(row1);
606 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, val);
607 put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
608 table.put(put);
609 Get get = new Get(row1);
610 get.setAuthorizations(new Authorizations(SECRET));
611 Result result = table.get(get);
612 assertTrue(result.isEmpty());
613 table.incrementColumnValue(row1, fam, qual, 2L);
614 result = table.get(get);
615 assertTrue(result.isEmpty());
616 Increment increment = new Increment(row1);
617 increment.addColumn(fam, qual, 2L);
618 increment.setCellVisibility(new CellVisibility(SECRET));
619 table.increment(increment);
620 result = table.get(get);
621 assertTrue(!result.isEmpty());
622 }
623 }
624
625 @Test
626 public void testLabelsWithAppend() throws Throwable {
627 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
628 try (Table table = TEST_UTIL.createTable(tableName, fam);) {
629 byte[] row1 = Bytes.toBytes("row1");
630 byte[] val = Bytes.toBytes("a");
631 Put put = new Put(row1);
632 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, val);
633 put.setCellVisibility(new CellVisibility(SECRET + " & " + CONFIDENTIAL));
634 table.put(put);
635 Get get = new Get(row1);
636 get.setAuthorizations(new Authorizations(SECRET));
637 Result result = table.get(get);
638 assertTrue(result.isEmpty());
639 Append append = new Append(row1);
640 append.add(fam, qual, Bytes.toBytes("b"));
641 table.append(append);
642 result = table.get(get);
643 assertTrue(result.isEmpty());
644 append = new Append(row1);
645 append.add(fam, qual, Bytes.toBytes("c"));
646 append.setCellVisibility(new CellVisibility(SECRET));
647 table.append(append);
648 result = table.get(get);
649 assertTrue(!result.isEmpty());
650 }
651 }
652
653 @Test
654 public void testUserShouldNotDoDDLOpOnLabelsTable() throws Exception {
655 Admin admin = TEST_UTIL.getHBaseAdmin();
656 try {
657 admin.disableTable(LABELS_TABLE_NAME);
658 fail("Lables table should not get disabled by user.");
659 } catch (Exception e) {
660 }
661 try {
662 admin.deleteTable(LABELS_TABLE_NAME);
663 fail("Lables table should not get disabled by user.");
664 } catch (Exception e) {
665 }
666 try {
667 HColumnDescriptor hcd = new HColumnDescriptor("testFamily");
668 admin.addColumn(LABELS_TABLE_NAME, hcd);
669 fail("Lables table should not get altered by user.");
670 } catch (Exception e) {
671 }
672 try {
673 admin.deleteColumn(LABELS_TABLE_NAME, VisibilityConstants.LABELS_TABLE_FAMILY);
674 fail("Lables table should not get altered by user.");
675 } catch (Exception e) {
676 }
677 try {
678 HColumnDescriptor hcd = new HColumnDescriptor(VisibilityConstants.LABELS_TABLE_FAMILY);
679 hcd.setBloomFilterType(BloomType.ROWCOL);
680 admin.modifyColumn(LABELS_TABLE_NAME, hcd);
681 fail("Lables table should not get altered by user.");
682 } catch (Exception e) {
683 }
684 try {
685 HTableDescriptor htd = new HTableDescriptor(LABELS_TABLE_NAME);
686 htd.addFamily(new HColumnDescriptor("f1"));
687 htd.addFamily(new HColumnDescriptor("f2"));
688 admin.modifyTable(LABELS_TABLE_NAME, htd);
689 fail("Lables table should not get altered by user.");
690 } catch (Exception e) {
691 }
692 }
693
694 @Test
695 public void testMultipleVersions() throws Exception {
696 final byte[] r1 = Bytes.toBytes("row1");
697 final byte[] r2 = Bytes.toBytes("row2");
698 final byte[] v1 = Bytes.toBytes("100");
699 final byte[] v2 = Bytes.toBytes("101");
700 final byte[] fam2 = Bytes.toBytes("info2");
701 final byte[] qual2 = Bytes.toBytes("qual2");
702 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
703 HTableDescriptor desc = new HTableDescriptor(tableName);
704 HColumnDescriptor col = new HColumnDescriptor(fam);
705 desc.addFamily(col);
706 col = new HColumnDescriptor(fam2);
707 col.setMaxVersions(5);
708 desc.addFamily(col);
709 TEST_UTIL.getHBaseAdmin().createTable(desc);
710 try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
711 Put put = new Put(r1);
712 put.add(fam, qual, 3l, v1);
713 put.add(fam, qual2, 3l, v1);
714 put.add(fam2, qual, 3l, v1);
715 put.add(fam2, qual2, 3l, v1);
716 put.setCellVisibility(new CellVisibility(SECRET));
717 table.put(put);
718 put = new Put(r1);
719 put.add(fam, qual, 4l, v2);
720 put.add(fam, qual2, 4l, v2);
721 put.add(fam2, qual, 4l, v2);
722 put.add(fam2, qual2, 4l, v2);
723 put.setCellVisibility(new CellVisibility(PRIVATE));
724 table.put(put);
725
726 put = new Put(r2);
727 put.add(fam, qual, 3l, v1);
728 put.add(fam, qual2, 3l, v1);
729 put.add(fam2, qual, 3l, v1);
730 put.add(fam2, qual2, 3l, v1);
731 put.setCellVisibility(new CellVisibility(SECRET));
732 table.put(put);
733 put = new Put(r2);
734 put.add(fam, qual, 4l, v2);
735 put.add(fam, qual2, 4l, v2);
736 put.add(fam2, qual, 4l, v2);
737 put.add(fam2, qual2, 4l, v2);
738 put.setCellVisibility(new CellVisibility(SECRET));
739 table.put(put);
740
741 Scan s = new Scan();
742 s.setMaxVersions(1);
743 s.setAuthorizations(new Authorizations(SECRET));
744 ResultScanner scanner = table.getScanner(s);
745 Result result = scanner.next();
746 assertTrue(Bytes.equals(r1, result.getRow()));
747
748
749
750 assertNull(result.getColumnLatestCell(fam, qual));
751 assertNull(result.getColumnLatestCell(fam, qual2));
752
753
754
755
756 Cell cell = result.getColumnLatestCell(fam2, qual);
757 assertNotNull(cell);
758 assertTrue(Bytes.equals(v1, 0, v1.length, cell.getValueArray(), cell.getValueOffset(),
759 cell.getValueLength()));
760 cell = result.getColumnLatestCell(fam2, qual2);
761 assertNotNull(cell);
762 assertTrue(Bytes.equals(v1, 0, v1.length, cell.getValueArray(), cell.getValueOffset(),
763 cell.getValueLength()));
764
765 result = scanner.next();
766 assertTrue(Bytes.equals(r2, result.getRow()));
767 cell = result.getColumnLatestCell(fam, qual);
768 assertNotNull(cell);
769 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
770 cell.getValueLength()));
771 cell = result.getColumnLatestCell(fam, qual2);
772 assertNotNull(cell);
773 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
774 cell.getValueLength()));
775 cell = result.getColumnLatestCell(fam2, qual);
776 assertNotNull(cell);
777 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
778 cell.getValueLength()));
779 cell = result.getColumnLatestCell(fam2, qual2);
780 assertNotNull(cell);
781 assertTrue(Bytes.equals(v2, 0, v2.length, cell.getValueArray(), cell.getValueOffset(),
782 cell.getValueLength()));
783 }
784 }
785
786 @Test
787 public void testMutateRow() throws Exception {
788 final byte[] qual2 = Bytes.toBytes("qual2");
789 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
790 HTableDescriptor desc = new HTableDescriptor(tableName);
791 HColumnDescriptor col = new HColumnDescriptor(fam);
792 desc.addFamily(col);
793 TEST_UTIL.getHBaseAdmin().createTable(desc);
794 try (Table table = TEST_UTIL.getConnection().getTable(tableName)){
795 Put p1 = new Put(row1);
796 p1.add(fam, qual, value);
797 p1.setCellVisibility(new CellVisibility(CONFIDENTIAL));
798
799 Put p2 = new Put(row1);
800 p2.add(fam, qual2, value);
801 p2.setCellVisibility(new CellVisibility(SECRET));
802
803 RowMutations rm = new RowMutations(row1);
804 rm.add(p1);
805 rm.add(p2);
806
807 table.mutateRow(rm);
808
809 Get get = new Get(row1);
810 get.setAuthorizations(new Authorizations(CONFIDENTIAL));
811 Result result = table.get(get);
812 assertTrue(result.containsColumn(fam, qual));
813 assertFalse(result.containsColumn(fam, qual2));
814
815 get.setAuthorizations(new Authorizations(SECRET));
816 result = table.get(get);
817 assertFalse(result.containsColumn(fam, qual));
818 assertTrue(result.containsColumn(fam, qual2));
819 }
820 }
821
822 @Test
823 public void testFlushedFileWithVisibilityTags() throws Exception {
824 final byte[] qual2 = Bytes.toBytes("qual2");
825 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
826 HTableDescriptor desc = new HTableDescriptor(tableName);
827 HColumnDescriptor col = new HColumnDescriptor(fam);
828 desc.addFamily(col);
829 TEST_UTIL.getHBaseAdmin().createTable(desc);
830 try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
831 Put p1 = new Put(row1);
832 p1.add(fam, qual, value);
833 p1.setCellVisibility(new CellVisibility(CONFIDENTIAL));
834
835 Put p2 = new Put(row1);
836 p2.add(fam, qual2, value);
837 p2.setCellVisibility(new CellVisibility(SECRET));
838
839 RowMutations rm = new RowMutations(row1);
840 rm.add(p1);
841 rm.add(p2);
842
843 table.mutateRow(rm);
844 }
845 TEST_UTIL.getHBaseAdmin().flush(tableName);
846 List<HRegion> regions = TEST_UTIL.getHBaseCluster().getRegions(tableName);
847 Store store = regions.get(0).getStore(fam);
848 Collection<StoreFile> storefiles = store.getStorefiles();
849 assertTrue(storefiles.size() > 0);
850 for (StoreFile storeFile : storefiles) {
851 assertTrue(storeFile.getReader().getHFileReader().getFileContext().isIncludesTags());
852 }
853 }
854
855 static Table createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)
856 throws Exception {
857 List<Put> puts = new ArrayList<Put>();
858 for (int i = 0; i < labelExps.length; i++) {
859 Put put = new Put(Bytes.toBytes("row" + (i+1)));
860 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
861 put.setCellVisibility(new CellVisibility(labelExps[i]));
862 puts.add(put);
863 }
864 Table table = TEST_UTIL.createTable(tableName, fam);
865 table.put(puts);
866 return table;
867 }
868
869 public static void addLabels() throws Exception {
870 PrivilegedExceptionAction<VisibilityLabelsResponse> action =
871 new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
872 public VisibilityLabelsResponse run() throws Exception {
873 String[] labels = { SECRET, TOPSECRET, CONFIDENTIAL, PUBLIC, PRIVATE, COPYRIGHT, ACCENT,
874 UNICODE_VIS_TAG, UC1, UC2 };
875 try (Connection conn = ConnectionFactory.createConnection(conf)) {
876 VisibilityClient.addLabels(conn, labels);
877 } catch (Throwable t) {
878 throw new IOException(t);
879 }
880 return null;
881 }
882 };
883 SUPERUSER.runAs(action);
884 }
885 }