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     // Test that super user can see all the cells.
125     SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
126       public Void run() throws Exception {
127         HTable table = new HTable(conf, tableName);
128         try {
129           Scan s = new Scan();
130           ResultScanner scanner = table.getScanner(s);
131           Result[] next = scanner.next(1);
132 
133           // Test that super user can see all the cells.
134           assertTrue(next.length == 1);
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(), ROW_1, 0, ROW_1.length));
140           assertTrue(Bytes.equals(current.getQualifier(), Q1));
141           assertTrue(Bytes.equals(current.getValue(), value1));
142           cellScanner.advance();
143           current = cellScanner.current();
144           assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
145               current.getRowLength(), ROW_1, 0, ROW_1.length));
146           assertTrue(Bytes.equals(current.getQualifier(), Q2));
147           assertTrue(Bytes.equals(current.getValue(), value2));
148           cellScanner.advance();
149           current = cellScanner.current();
150           assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
151               current.getRowLength(), ROW_1, 0, ROW_1.length));
152           assertTrue(Bytes.equals(current.getQualifier(), Q3));
153           assertTrue(Bytes.equals(current.getValue(), value3));
154 
155           return null;
156         } finally {
157           table.close();
158         }
159       }
160     });
161 
162     TESTUSER.runAs(new PrivilegedExceptionAction<Void>() {
163       public Void run() throws Exception {
164         HTable table = new HTable(conf, tableName);
165         try {
166           // Test scan with no auth attribute
167           Scan s = new Scan();
168           ResultScanner scanner = table.getScanner(s);
169           Result[] next = scanner.next(1);
170 
171           assertTrue(next.length == 1);
172           CellScanner cellScanner = next[0].cellScanner();
173           cellScanner.advance();
174           Cell current = cellScanner.current();
175           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
176           assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
177               current.getRowLength(), ROW_1, 0, ROW_1.length));
178           assertTrue(Bytes.equals(current.getQualifier(), Q2));
179           assertTrue(Bytes.equals(current.getValue(), value2));
180           cellScanner.advance();
181           current = cellScanner.current();
182           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
183           assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
184               current.getRowLength(), ROW_1, 0, ROW_1.length));
185           assertTrue(Bytes.equals(current.getQualifier(), Q3));
186           assertTrue(Bytes.equals(current.getValue(), value3));
187 
188           // Test scan with correct auth attribute for test user
189           Scan s1 = new Scan();
190           // test user is entitled to 'CONFIDENTIAL'.
191           // If we set both labels in the scan, 'SECRET' will be dropped by the SLGs.
192           s1.setAuthorizations(new Authorizations(new String[] { SECRET, CONFIDENTIAL }));
193           ResultScanner scanner1 = table.getScanner(s1);
194           Result[] next1 = scanner1.next(1);
195 
196           assertTrue(next1.length == 1);
197           CellScanner cellScanner1 = next1[0].cellScanner();
198           cellScanner1.advance();
199           Cell current1 = cellScanner1.current();
200           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
201           assertTrue(Bytes.equals(current1.getRowArray(), current1.getRowOffset(),
202             current1.getRowLength(), ROW_1, 0, ROW_1.length));
203           assertTrue(Bytes.equals(current1.getQualifier(), Q2));
204           assertTrue(Bytes.equals(current1.getValue(), value2));
205           cellScanner1.advance();
206           current1 = cellScanner1.current();
207           // test user can see value2 (CONFIDENTIAL) and value3 (no label)
208           assertTrue(Bytes.equals(current1.getRowArray(), current1.getRowOffset(),
209             current1.getRowLength(), ROW_1, 0, ROW_1.length));
210           assertTrue(Bytes.equals(current1.getQualifier(), Q3));
211           assertTrue(Bytes.equals(current1.getValue(), value3));
212 
213           // Test scan with incorrect auth attribute for test user
214           Scan s2 = new Scan();
215           // test user is entitled to 'CONFIDENTIAL'.
216           // If we set 'SECRET', it will be dropped by the SLGs.
217           s2.setAuthorizations(new Authorizations(new String[] { SECRET }));
218           ResultScanner scanner2 = table.getScanner(s2);
219           Result next2 = scanner2.next();
220           CellScanner cellScanner2 = next2.cellScanner();
221           cellScanner2.advance();
222           Cell current2 = cellScanner2.current();
223           // This scan will only see value3 (no label)
224           assertTrue(Bytes.equals(current2.getRowArray(), current2.getRowOffset(),
225             current2.getRowLength(), ROW_1, 0, ROW_1.length));
226           assertTrue(Bytes.equals(current2.getQualifier(), Q3));
227           assertTrue(Bytes.equals(current2.getValue(), value3));
228 
229           assertFalse(cellScanner2.advance());
230 
231           return null;
232         } finally {
233           table.close();
234         }
235       }
236     });
237 
238   }
239 
240   @AfterClass
241   public static void tearDownAfterClass() throws Exception {
242     TEST_UTIL.shutdownMiniCluster();
243   }
244 }