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_NAME;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertTrue;
23  import static org.junit.Assert.assertNull;
24  
25  import java.io.IOException;
26  import java.security.PrivilegedExceptionAction;
27  
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.Cell;
30  import org.apache.hadoop.hbase.CellScanner;
31  import org.apache.hadoop.hbase.HBaseTestingUtility;
32  import org.apache.hadoop.hbase.HConstants;
33  import org.apache.hadoop.hbase.testclassification.MediumTests;
34  import org.apache.hadoop.hbase.TableName;
35  import org.apache.hadoop.hbase.client.HTable;
36  import org.apache.hadoop.hbase.client.Put;
37  import org.apache.hadoop.hbase.client.Result;
38  import org.apache.hadoop.hbase.client.ResultScanner;
39  import org.apache.hadoop.hbase.client.Scan;
40  import org.apache.hadoop.hbase.security.User;
41  import org.apache.hadoop.hbase.util.Bytes;
42  import org.junit.AfterClass;
43  import org.junit.BeforeClass;
44  import org.junit.Rule;
45  import org.junit.Test;
46  import org.junit.experimental.categories.Category;
47  import org.junit.rules.TestName;
48  
49  @Category(MediumTests.class)
50  public class TestDefaultScanLabelGeneratorStack {
51  
52    public static final String CONFIDENTIAL = "confidential";
53    private static final String SECRET = "secret";
54    public static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
55    private static final byte[] ROW_1 = Bytes.toBytes("row1");
56    private final static byte[] CF = Bytes.toBytes("f");
57    private final static byte[] Q1 = Bytes.toBytes("q1");
58    private final static byte[] Q2 = Bytes.toBytes("q2");
59    private final static byte[] Q3 = Bytes.toBytes("q3");
60    private final static byte[] value1 = Bytes.toBytes("value1");
61    private final static byte[] value2 = Bytes.toBytes("value2");
62    private final static byte[] value3 = Bytes.toBytes("value3");
63    public static Configuration conf;
64  
65    @Rule
66    public final TestName TEST_NAME = new TestName();
67    public static User SUPERUSER;
68    public static User TESTUSER;
69  
70    @BeforeClass
71    public static void setupBeforeClass() throws Exception {
72      // setup configuration
73      conf = TEST_UTIL.getConfiguration();
74      VisibilityTestUtil.enableVisiblityLabels(conf);
75      // Not setting any SLG class. This means to use the default behavior.
76      conf.set("hbase.superuser", "admin");
77      TEST_UTIL.startMiniCluster(1);
78      SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
79      TESTUSER = User.createUserForTesting(conf, "test", new String[] { });
80  
81      // Wait for the labels table to become available
82      TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
83  
84      // Set up for the test
85      SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
86        public Void run() throws Exception {
87          try {
88            VisibilityClient.addLabels(conf, new String[] { SECRET, CONFIDENTIAL });
89            VisibilityClient.setAuths(conf, new String[] { CONFIDENTIAL }, TESTUSER.getShortName());
90          } catch (Throwable t) {
91            throw new IOException(t);
92          }
93          return null;
94        }
95      });
96    }
97  
98    @Test
99    public void testDefaultScanLabelGeneratorStack() throws Exception {
100     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
101 
102     SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
103       public Void run() throws Exception {
104         HTable table = TEST_UTIL.createTable(tableName, CF);
105         try {
106           Put put = new Put(ROW_1);
107           put.add(CF, Q1, HConstants.LATEST_TIMESTAMP, value1);
108           put.setCellVisibility(new CellVisibility(SECRET));
109           table.put(put);
110           put = new Put(ROW_1);
111           put.add(CF, Q2, HConstants.LATEST_TIMESTAMP, value2);
112           put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
113           table.put(put);
114           put = new Put(ROW_1);
115           put.add(CF, Q3, HConstants.LATEST_TIMESTAMP, value3);
116           table.put(put);
117           return null;
118         } finally {
119           table.close();
120         }
121       }
122     });
123 
124     TESTUSER.runAs(new PrivilegedExceptionAction<Void>() {
125       public Void run() throws Exception {
126         HTable table = new HTable(conf, tableName);
127         try {
128           // Test scan with no auth attribute
129           Scan s = new Scan();
130           ResultScanner scanner = table.getScanner(s);
131           Result[] next = scanner.next(1);
132 
133           assertTrue(next.length == 1);
134           CellScanner cellScanner = next[0].cellScanner();
135           cellScanner.advance();
136           Cell current = cellScanner.current();
137           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
138           assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
139               current.getRowLength(), ROW_1, 0, ROW_1.length));
140           assertTrue(Bytes.equals(current.getQualifier(), Q2));
141           assertTrue(Bytes.equals(current.getValue(), value2));
142           cellScanner.advance();
143           current = cellScanner.current();
144           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
145           assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
146               current.getRowLength(), ROW_1, 0, ROW_1.length));
147           assertTrue(Bytes.equals(current.getQualifier(), Q3));
148           assertTrue(Bytes.equals(current.getValue(), value3));
149 
150           // Test scan with correct auth attribute for test user
151           Scan s1 = new Scan();
152           // test user is entitled to 'CONFIDENTIAL'.
153           // If we set both labels in the scan, 'SECRET' will be dropped by the SLGs.
154           s1.setAuthorizations(new Authorizations(new String[] { SECRET, CONFIDENTIAL }));
155           ResultScanner scanner1 = table.getScanner(s1);
156           Result[] next1 = scanner1.next(1);
157 
158           assertTrue(next1.length == 1);
159           CellScanner cellScanner1 = next1[0].cellScanner();
160           cellScanner1.advance();
161           Cell current1 = cellScanner1.current();
162           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
163           assertTrue(Bytes.equals(current1.getRowArray(), current1.getRowOffset(),
164             current1.getRowLength(), ROW_1, 0, ROW_1.length));
165           assertTrue(Bytes.equals(current1.getQualifier(), Q2));
166           assertTrue(Bytes.equals(current1.getValue(), value2));
167           cellScanner1.advance();
168           current1 = cellScanner1.current();
169           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
170           assertTrue(Bytes.equals(current1.getRowArray(), current1.getRowOffset(),
171             current1.getRowLength(), ROW_1, 0, ROW_1.length));
172           assertTrue(Bytes.equals(current1.getQualifier(), Q3));
173           assertTrue(Bytes.equals(current1.getValue(), value3));
174 
175           // Test scan with incorrect auth attribute for test user
176           Scan s2 = new Scan();
177           // test user is entitled to 'CONFIDENTIAL'.
178           // If we set 'SECRET', it will be dropped by the SLGs.
179           s2.setAuthorizations(new Authorizations(new String[] { SECRET }));
180           ResultScanner scanner2 = table.getScanner(s2);
181           Result next2 = scanner2.next();
182           CellScanner cellScanner2 = next2.cellScanner();
183           cellScanner2.advance();
184           Cell current2 = cellScanner2.current();
185           // This scan will only see value3 (no label)
186           assertTrue(Bytes.equals(current2.getRowArray(), current2.getRowOffset(),
187             current2.getRowLength(), ROW_1, 0, ROW_1.length));
188           assertTrue(Bytes.equals(current2.getQualifier(), Q3));
189           assertTrue(Bytes.equals(current2.getValue(), value3));
190 
191           assertFalse(cellScanner2.advance());
192 
193 
194           return null;
195         } finally {
196           table.close();
197         }
198       }
199     });
200 
201   }
202 
203   @AfterClass
204   public static void tearDownAfterClass() throws Exception {
205     TEST_UTIL.shutdownMiniCluster();
206   }
207 }