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.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023import static org.junit.jupiter.api.Assertions.fail; 024 025import java.security.PrivilegedExceptionAction; 026import java.util.ArrayList; 027import java.util.List; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.hbase.HBaseTestingUtil; 030import org.apache.hadoop.hbase.HConstants; 031import org.apache.hadoop.hbase.TableName; 032import org.apache.hadoop.hbase.client.Connection; 033import org.apache.hadoop.hbase.client.ConnectionFactory; 034import org.apache.hadoop.hbase.client.Put; 035import org.apache.hadoop.hbase.client.Result; 036import org.apache.hadoop.hbase.client.ResultScanner; 037import org.apache.hadoop.hbase.client.Scan; 038import org.apache.hadoop.hbase.client.Table; 039import org.apache.hadoop.hbase.security.User; 040import org.apache.hadoop.hbase.security.access.SecureTestUtil; 041import org.apache.hadoop.hbase.testclassification.LargeTests; 042import org.apache.hadoop.hbase.testclassification.SecurityTests; 043import org.apache.hadoop.hbase.util.Bytes; 044import org.junit.jupiter.api.AfterAll; 045import org.junit.jupiter.api.BeforeAll; 046import org.junit.jupiter.api.Tag; 047import org.junit.jupiter.api.Test; 048import org.junit.jupiter.api.TestInfo; 049 050import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; 051 052import org.apache.hadoop.hbase.shaded.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse; 053 054@Tag(SecurityTests.TAG) 055@Tag(LargeTests.TAG) 056public class TestWithDisabledAuthorization { 057 058 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 059 060 private static final String CONFIDENTIAL = "confidential"; 061 private static final String SECRET = "secret"; 062 private static final String PRIVATE = "private"; 063 private static final byte[] TEST_FAMILY = Bytes.toBytes("test"); 064 private static final byte[] TEST_QUALIFIER = Bytes.toBytes("q"); 065 private static final byte[] ZERO = Bytes.toBytes(0L); 066 067 private static User SUPERUSER; 068 private static User USER_RW; 069 private static Configuration conf; 070 071 @BeforeAll 072 public static void setUpBeforeClass() throws Exception { 073 conf = TEST_UTIL.getConfiguration(); 074 // Up the handlers; this test needs more than usual. 075 conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10); 076 // Set up superuser 077 SecureTestUtil.configureSuperuser(conf); 078 079 // Install the VisibilityController as a system processor 080 VisibilityTestUtil.enableVisiblityLabels(conf); 081 082 // Now, DISABLE active authorization 083 conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false); 084 085 TEST_UTIL.startMiniCluster(); 086 087 // Wait for the labels table to become available 088 TEST_UTIL.waitUntilAllRegionsAssigned(LABELS_TABLE_NAME); 089 090 // create a set of test users 091 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 092 USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]); 093 094 // Define test labels 095 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 096 @Override 097 public Void run() throws Exception { 098 try (Connection conn = ConnectionFactory.createConnection(conf)) { 099 VisibilityClient.addLabels(conn, new String[] { SECRET, CONFIDENTIAL, PRIVATE }); 100 VisibilityClient.setAuths(conn, new String[] { SECRET, CONFIDENTIAL }, 101 USER_RW.getShortName()); 102 } catch (Throwable t) { 103 fail("Should not have failed"); 104 } 105 return null; 106 } 107 }); 108 } 109 110 @AfterAll 111 public static void tearDownAfterClass() throws Exception { 112 TEST_UTIL.shutdownMiniCluster(); 113 } 114 115 @Test 116 public void testManageUserAuths() throws Throwable { 117 // Even though authorization is disabled, we should be able to manage user auths 118 119 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 120 @Override 121 public Void run() throws Exception { 122 try (Connection conn = ConnectionFactory.createConnection(conf)) { 123 VisibilityClient.setAuths(conn, new String[] { SECRET, CONFIDENTIAL }, 124 USER_RW.getShortName()); 125 } catch (Throwable t) { 126 fail("Should not have failed"); 127 } 128 return null; 129 } 130 }); 131 132 PrivilegedExceptionAction<List<String>> getAuths = 133 new PrivilegedExceptionAction<List<String>>() { 134 @Override 135 public List<String> run() throws Exception { 136 GetAuthsResponse authsResponse = null; 137 try (Connection conn = ConnectionFactory.createConnection(conf)) { 138 authsResponse = VisibilityClient.getAuths(conn, USER_RW.getShortName()); 139 } catch (Throwable t) { 140 fail("Should not have failed"); 141 } 142 List<String> authsList = new ArrayList<>(authsResponse.getAuthList().size()); 143 for (ByteString authBS : authsResponse.getAuthList()) { 144 authsList.add(Bytes.toString(authBS.toByteArray())); 145 } 146 return authsList; 147 } 148 }; 149 150 List<String> authsList = SUPERUSER.runAs(getAuths); 151 assertEquals(2, authsList.size()); 152 assertTrue(authsList.contains(SECRET)); 153 assertTrue(authsList.contains(CONFIDENTIAL)); 154 155 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 156 @Override 157 public Void run() throws Exception { 158 try (Connection conn = ConnectionFactory.createConnection(conf)) { 159 VisibilityClient.clearAuths(conn, new String[] { SECRET }, USER_RW.getShortName()); 160 } catch (Throwable t) { 161 fail("Should not have failed"); 162 } 163 return null; 164 } 165 }); 166 167 authsList = SUPERUSER.runAs(getAuths); 168 assertEquals(1, authsList.size()); 169 assertTrue(authsList.contains(CONFIDENTIAL)); 170 171 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 172 @Override 173 public Void run() throws Exception { 174 try (Connection conn = ConnectionFactory.createConnection(conf)) { 175 VisibilityClient.clearAuths(conn, new String[] { CONFIDENTIAL }, USER_RW.getShortName()); 176 } catch (Throwable t) { 177 fail("Should not have failed"); 178 } 179 return null; 180 } 181 }); 182 183 authsList = SUPERUSER.runAs(getAuths); 184 assertEquals(0, authsList.size()); 185 } 186 187 @Test 188 public void testPassiveVisibility(TestInfo testInfo) throws Exception { 189 // No values should be filtered regardless of authorization if we are passive 190 try (Table t = 191 createTableAndWriteDataWithLabels(TableName.valueOf(testInfo.getTestMethod().get().getName()), 192 SECRET, PRIVATE, SECRET + "|" + CONFIDENTIAL, PRIVATE + "|" + CONFIDENTIAL)) { 193 Scan s = new Scan(); 194 s.setAuthorizations(new Authorizations()); 195 try (ResultScanner scanner = t.getScanner(s)) { 196 Result[] next = scanner.next(10); 197 assertEquals(4, next.length); 198 } 199 s = new Scan(); 200 s.setAuthorizations(new Authorizations(SECRET)); 201 try (ResultScanner scanner = t.getScanner(s)) { 202 Result[] next = scanner.next(10); 203 assertEquals(4, next.length); 204 } 205 s = new Scan(); 206 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL)); 207 try (ResultScanner scanner = t.getScanner(s)) { 208 Result[] next = scanner.next(10); 209 assertEquals(4, next.length); 210 } 211 s = new Scan(); 212 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL, PRIVATE)); 213 try (ResultScanner scanner = t.getScanner(s)) { 214 Result[] next = scanner.next(10); 215 assertEquals(4, next.length); 216 } 217 } 218 } 219 220 static Table createTableAndWriteDataWithLabels(TableName tableName, String... labelExps) 221 throws Exception { 222 List<Put> puts = new ArrayList<>(labelExps.length + 1); 223 for (int i = 0; i < labelExps.length; i++) { 224 Put put = new Put(Bytes.toBytes("row" + (i + 1))); 225 put.addColumn(TEST_FAMILY, TEST_QUALIFIER, HConstants.LATEST_TIMESTAMP, ZERO); 226 put.setCellVisibility(new CellVisibility(labelExps[i])); 227 puts.add(put); 228 } 229 Table table = TEST_UTIL.createTable(tableName, TEST_FAMILY); 230 table.put(puts); 231 return table; 232 } 233}