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.*;
22 
23 import java.security.PrivilegedExceptionAction;
24 import java.util.ArrayList;
25 import java.util.List;
26 
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.hbase.HBaseTestingUtility;
29 import org.apache.hadoop.hbase.HConstants;
30 import org.apache.hadoop.hbase.TableName;
31 import org.apache.hadoop.hbase.client.Connection;
32 import org.apache.hadoop.hbase.client.ConnectionFactory;
33 import org.apache.hadoop.hbase.client.Put;
34 import org.apache.hadoop.hbase.client.Result;
35 import org.apache.hadoop.hbase.client.ResultScanner;
36 import org.apache.hadoop.hbase.client.Scan;
37 import org.apache.hadoop.hbase.client.Table;
38 import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
39 import org.apache.hadoop.hbase.security.User;
40 import org.apache.hadoop.hbase.security.access.SecureTestUtil;
41 import org.apache.hadoop.hbase.testclassification.LargeTests;
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 import com.google.protobuf.ByteString;
51 
52 @Category(LargeTests.class)
53 public class TestWithDisabledAuthorization {
54 
55   private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
56 
57   private static final String CONFIDENTIAL = "confidential";
58   private static final String SECRET = "secret";
59   private static final String PRIVATE = "private";
60   private static final byte[] TEST_FAMILY = Bytes.toBytes("test");
61   private static final byte[] TEST_QUALIFIER = Bytes.toBytes("q");
62   private static final byte[] ZERO = Bytes.toBytes(0L);
63 
64 
65   @Rule
66   public final TestName TEST_NAME = new TestName();
67 
68   private static User SUPERUSER;
69   private static User USER_RW;
70   private static Configuration conf;
71 
72   @BeforeClass
setUpBeforeClass()73   public static void setUpBeforeClass() throws Exception {
74     conf = TEST_UTIL.getConfiguration();
75     // Up the handlers; this test needs more than usual.
76     conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10);
77     // Set up superuser
78     SecureTestUtil.configureSuperuser(conf);
79 
80     // Install the VisibilityController as a system processor
81     VisibilityTestUtil.enableVisiblityLabels(conf);
82 
83     // Now, DISABLE active authorization
84     conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);
85 
86     TEST_UTIL.startMiniCluster();
87 
88     // Wait for the labels table to become available
89     TEST_UTIL.waitUntilAllRegionsAssigned(LABELS_TABLE_NAME);
90 
91     // create a set of test users
92     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
93     USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
94 
95     // Define test labels
96     SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
97       public Void run() throws Exception {
98         try (Connection conn = ConnectionFactory.createConnection(conf)) {
99           VisibilityClient.addLabels(conn,
100             new String[] { SECRET, CONFIDENTIAL, PRIVATE });
101           VisibilityClient.setAuths(conn,
102             new String[] { SECRET, CONFIDENTIAL },
103             USER_RW.getShortName());
104         } catch (Throwable t) {
105           fail("Should not have failed");
106         }
107         return null;
108       }
109     });
110   }
111 
112   @AfterClass
tearDownAfterClass()113   public static void tearDownAfterClass() throws Exception {
114     TEST_UTIL.shutdownMiniCluster();
115   }
116 
117   @Test (timeout=180000)
testManageUserAuths()118   public void testManageUserAuths() throws Throwable {
119     // Even though authorization is disabled, we should be able to manage user auths
120 
121     SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
122       public Void run() throws Exception {
123         try (Connection conn = ConnectionFactory.createConnection(conf)) {
124           VisibilityClient.setAuths(conn,
125             new String[] { SECRET, CONFIDENTIAL },
126             USER_RW.getShortName());
127         } catch (Throwable t) {
128           fail("Should not have failed");
129         }
130         return null;
131       }
132     });
133 
134     PrivilegedExceptionAction<List<String>> getAuths =
135       new PrivilegedExceptionAction<List<String>>() {
136         public List<String> run() throws Exception {
137           GetAuthsResponse authsResponse = null;
138           try (Connection conn = ConnectionFactory.createConnection(conf)) {
139             authsResponse = VisibilityClient.getAuths(conn,
140               USER_RW.getShortName());
141           } catch (Throwable t) {
142             fail("Should not have failed");
143           }
144           List<String> authsList = new ArrayList<String>();
145           for (ByteString authBS : authsResponse.getAuthList()) {
146             authsList.add(Bytes.toString(authBS.toByteArray()));
147           }
148           return authsList;
149         }
150       };
151 
152     List<String> authsList = SUPERUSER.runAs(getAuths);
153     assertEquals(2, authsList.size());
154     assertTrue(authsList.contains(SECRET));
155     assertTrue(authsList.contains(CONFIDENTIAL));
156 
157     SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
158       public Void run() throws Exception {
159         try (Connection conn = ConnectionFactory.createConnection(conf)) {
160           VisibilityClient.clearAuths(conn,
161             new String[] { SECRET },
162             USER_RW.getShortName());
163         } catch (Throwable t) {
164           fail("Should not have failed");
165         }
166         return null;
167       }
168     });
169 
170     authsList = SUPERUSER.runAs(getAuths);
171     assertEquals(1, authsList.size());
172     assertTrue(authsList.contains(CONFIDENTIAL));
173 
174     SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() {
175       public Void run() throws Exception {
176         try (Connection conn = ConnectionFactory.createConnection(conf)) {
177           VisibilityClient.clearAuths(conn,
178             new String[] { CONFIDENTIAL },
179             USER_RW.getShortName());
180         } catch (Throwable t) {
181           fail("Should not have failed");
182         }
183         return null;
184       }
185     });
186 
187     authsList = SUPERUSER.runAs(getAuths);
188     assertEquals(0, authsList.size());
189   }
190 
191   @Test (timeout=180000)
testPassiveVisibility()192   public void testPassiveVisibility() throws Exception {
193     // No values should be filtered regardless of authorization if we are passive
194     try (Table t = createTableAndWriteDataWithLabels(
195       TableName.valueOf(TEST_NAME.getMethodName()),
196         SECRET,
197         PRIVATE,
198         SECRET + "|" + CONFIDENTIAL,
199         PRIVATE + "|" + CONFIDENTIAL)) {
200       Scan s = new Scan();
201       s.setAuthorizations(new Authorizations());
202       try (ResultScanner scanner = t.getScanner(s)) {
203         Result[] next = scanner.next(10);
204         assertEquals(next.length, 4);
205       }
206       s = new Scan();
207       s.setAuthorizations(new Authorizations(SECRET));
208       try (ResultScanner scanner = t.getScanner(s)) {
209         Result[] next = scanner.next(10);
210         assertEquals(next.length, 4);
211       }
212       s = new Scan();
213       s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
214       try (ResultScanner scanner = t.getScanner(s)) {
215         Result[] next = scanner.next(10);
216         assertEquals(next.length, 4);
217       }
218       s = new Scan();
219       s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL, PRIVATE));
220       try (ResultScanner scanner = t.getScanner(s)) {
221         Result[] next = scanner.next(10);
222         assertEquals(next.length, 4);
223       }
224     }
225   }
226 
createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)227   static Table createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)
228       throws Exception {
229     List<Put> puts = new ArrayList<Put>();
230     for (int i = 0; i < labelExps.length; i++) {
231       Put put = new Put(Bytes.toBytes("row" + (i+1)));
232       put.addColumn(TEST_FAMILY, TEST_QUALIFIER, HConstants.LATEST_TIMESTAMP, ZERO);
233       put.setCellVisibility(new CellVisibility(labelExps[i]));
234       puts.add(put);
235     }
236     Table table = TEST_UTIL.createTable(tableName, TEST_FAMILY);
237     table.put(puts);
238     return table;
239   }
240 }
241