001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.security.visibility; 019 020import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertTrue; 023import static org.junit.Assert.fail; 024 025import com.google.protobuf.ByteString; 026import java.security.PrivilegedExceptionAction; 027import java.util.ArrayList; 028import java.util.List; 029import org.apache.hadoop.conf.Configuration; 030import org.apache.hadoop.hbase.HBaseClassTestRule; 031import org.apache.hadoop.hbase.HBaseTestingUtility; 032import org.apache.hadoop.hbase.HConstants; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.client.Connection; 035import org.apache.hadoop.hbase.client.ConnectionFactory; 036import org.apache.hadoop.hbase.client.Put; 037import org.apache.hadoop.hbase.client.Result; 038import org.apache.hadoop.hbase.client.ResultScanner; 039import org.apache.hadoop.hbase.client.Scan; 040import org.apache.hadoop.hbase.client.Table; 041import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse; 042import org.apache.hadoop.hbase.security.User; 043import org.apache.hadoop.hbase.security.access.SecureTestUtil; 044import org.apache.hadoop.hbase.testclassification.LargeTests; 045import org.apache.hadoop.hbase.testclassification.SecurityTests; 046import org.apache.hadoop.hbase.util.Bytes; 047import org.junit.AfterClass; 048import org.junit.BeforeClass; 049import org.junit.ClassRule; 050import org.junit.Rule; 051import org.junit.Test; 052import org.junit.experimental.categories.Category; 053import org.junit.rules.TestName; 054 055@Category({SecurityTests.class, LargeTests.class}) 056public class TestWithDisabledAuthorization { 057 058 @ClassRule 059 public static final HBaseClassTestRule CLASS_RULE = 060 HBaseClassTestRule.forClass(TestWithDisabledAuthorization.class); 061 062 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 063 064 private static final String CONFIDENTIAL = "confidential"; 065 private static final String SECRET = "secret"; 066 private static final String PRIVATE = "private"; 067 private static final byte[] TEST_FAMILY = Bytes.toBytes("test"); 068 private static final byte[] TEST_QUALIFIER = Bytes.toBytes("q"); 069 private static final byte[] ZERO = Bytes.toBytes(0L); 070 071 072 @Rule 073 public final TestName TEST_NAME = new TestName(); 074 075 private static User SUPERUSER; 076 private static User USER_RW; 077 private static Configuration conf; 078 079 @BeforeClass 080 public static void setUpBeforeClass() throws Exception { 081 conf = TEST_UTIL.getConfiguration(); 082 // Up the handlers; this test needs more than usual. 083 conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10); 084 // Set up superuser 085 SecureTestUtil.configureSuperuser(conf); 086 087 // Install the VisibilityController as a system processor 088 VisibilityTestUtil.enableVisiblityLabels(conf); 089 090 // Now, DISABLE active authorization 091 conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false); 092 093 TEST_UTIL.startMiniCluster(); 094 095 // Wait for the labels table to become available 096 TEST_UTIL.waitUntilAllRegionsAssigned(LABELS_TABLE_NAME); 097 098 // create a set of test users 099 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 100 USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]); 101 102 // Define test labels 103 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 104 @Override 105 public Void run() throws Exception { 106 try (Connection conn = ConnectionFactory.createConnection(conf)) { 107 VisibilityClient.addLabels(conn, 108 new String[] { SECRET, CONFIDENTIAL, PRIVATE }); 109 VisibilityClient.setAuths(conn, 110 new String[] { SECRET, CONFIDENTIAL }, 111 USER_RW.getShortName()); 112 } catch (Throwable t) { 113 fail("Should not have failed"); 114 } 115 return null; 116 } 117 }); 118 } 119 120 @AfterClass 121 public static void tearDownAfterClass() throws Exception { 122 TEST_UTIL.shutdownMiniCluster(); 123 } 124 125 @Test 126 public void testManageUserAuths() throws Throwable { 127 // Even though authorization is disabled, we should be able to manage user auths 128 129 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 130 @Override 131 public Void run() throws Exception { 132 try (Connection conn = ConnectionFactory.createConnection(conf)) { 133 VisibilityClient.setAuths(conn, 134 new String[] { SECRET, CONFIDENTIAL }, 135 USER_RW.getShortName()); 136 } catch (Throwable t) { 137 fail("Should not have failed"); 138 } 139 return null; 140 } 141 }); 142 143 PrivilegedExceptionAction<List<String>> getAuths = 144 new PrivilegedExceptionAction<List<String>>() { 145 @Override 146 public List<String> run() throws Exception { 147 GetAuthsResponse authsResponse = null; 148 try (Connection conn = ConnectionFactory.createConnection(conf)) { 149 authsResponse = VisibilityClient.getAuths(conn, 150 USER_RW.getShortName()); 151 } catch (Throwable t) { 152 fail("Should not have failed"); 153 } 154 List<String> authsList = new ArrayList<>(authsResponse.getAuthList().size()); 155 for (ByteString authBS : authsResponse.getAuthList()) { 156 authsList.add(Bytes.toString(authBS.toByteArray())); 157 } 158 return authsList; 159 } 160 }; 161 162 List<String> authsList = SUPERUSER.runAs(getAuths); 163 assertEquals(2, authsList.size()); 164 assertTrue(authsList.contains(SECRET)); 165 assertTrue(authsList.contains(CONFIDENTIAL)); 166 167 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 168 @Override 169 public Void run() throws Exception { 170 try (Connection conn = ConnectionFactory.createConnection(conf)) { 171 VisibilityClient.clearAuths(conn, 172 new String[] { SECRET }, 173 USER_RW.getShortName()); 174 } catch (Throwable t) { 175 fail("Should not have failed"); 176 } 177 return null; 178 } 179 }); 180 181 authsList = SUPERUSER.runAs(getAuths); 182 assertEquals(1, authsList.size()); 183 assertTrue(authsList.contains(CONFIDENTIAL)); 184 185 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 186 @Override 187 public Void run() throws Exception { 188 try (Connection conn = ConnectionFactory.createConnection(conf)) { 189 VisibilityClient.clearAuths(conn, 190 new String[] { CONFIDENTIAL }, 191 USER_RW.getShortName()); 192 } catch (Throwable t) { 193 fail("Should not have failed"); 194 } 195 return null; 196 } 197 }); 198 199 authsList = SUPERUSER.runAs(getAuths); 200 assertEquals(0, authsList.size()); 201 } 202 203 @Test 204 public void testPassiveVisibility() throws Exception { 205 // No values should be filtered regardless of authorization if we are passive 206 try (Table t = createTableAndWriteDataWithLabels( 207 TableName.valueOf(TEST_NAME.getMethodName()), 208 SECRET, 209 PRIVATE, 210 SECRET + "|" + CONFIDENTIAL, 211 PRIVATE + "|" + CONFIDENTIAL)) { 212 Scan s = new Scan(); 213 s.setAuthorizations(new Authorizations()); 214 try (ResultScanner scanner = t.getScanner(s)) { 215 Result[] next = scanner.next(10); 216 assertEquals(4, next.length); 217 } 218 s = new Scan(); 219 s.setAuthorizations(new Authorizations(SECRET)); 220 try (ResultScanner scanner = t.getScanner(s)) { 221 Result[] next = scanner.next(10); 222 assertEquals(4, next.length); 223 } 224 s = new Scan(); 225 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL)); 226 try (ResultScanner scanner = t.getScanner(s)) { 227 Result[] next = scanner.next(10); 228 assertEquals(4, next.length); 229 } 230 s = new Scan(); 231 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL, PRIVATE)); 232 try (ResultScanner scanner = t.getScanner(s)) { 233 Result[] next = scanner.next(10); 234 assertEquals(4, next.length); 235 } 236 } 237 } 238 239 static Table createTableAndWriteDataWithLabels(TableName tableName, String... labelExps) 240 throws Exception { 241 List<Put> puts = new ArrayList<>(labelExps.length + 1); 242 for (int i = 0; i < labelExps.length; i++) { 243 Put put = new Put(Bytes.toBytes("row" + (i+1))); 244 put.addColumn(TEST_FAMILY, TEST_QUALIFIER, HConstants.LATEST_TIMESTAMP, ZERO); 245 put.setCellVisibility(new CellVisibility(labelExps[i])); 246 puts.add(put); 247 } 248 Table table = TEST_UTIL.createTable(tableName, TEST_FAMILY); 249 table.put(puts); 250 return table; 251 } 252}