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