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