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 @Rule 072 public final TestName TEST_NAME = new TestName(); 073 074 private static User SUPERUSER; 075 private static User USER_RW; 076 private static Configuration conf; 077 078 @BeforeClass 079 public static void setUpBeforeClass() throws Exception { 080 conf = TEST_UTIL.getConfiguration(); 081 // Up the handlers; this test needs more than usual. 082 conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10); 083 // Set up superuser 084 SecureTestUtil.configureSuperuser(conf); 085 086 // Install the VisibilityController as a system processor 087 VisibilityTestUtil.enableVisiblityLabels(conf); 088 089 // Now, DISABLE active authorization 090 conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false); 091 092 TEST_UTIL.startMiniCluster(); 093 094 // Wait for the labels table to become available 095 TEST_UTIL.waitUntilAllRegionsAssigned(LABELS_TABLE_NAME); 096 097 // create a set of test users 098 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 099 USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]); 100 101 // Define test labels 102 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 103 @Override 104 public Void run() throws Exception { 105 try (Connection conn = ConnectionFactory.createConnection(conf)) { 106 VisibilityClient.addLabels(conn, new String[] { SECRET, CONFIDENTIAL, PRIVATE }); 107 VisibilityClient.setAuths(conn, new String[] { SECRET, CONFIDENTIAL }, 108 USER_RW.getShortName()); 109 } catch (Throwable t) { 110 fail("Should not have failed"); 111 } 112 return null; 113 } 114 }); 115 } 116 117 @AfterClass 118 public static void tearDownAfterClass() throws Exception { 119 TEST_UTIL.shutdownMiniCluster(); 120 } 121 122 @Test 123 public void testManageUserAuths() throws Throwable { 124 // Even though authorization is disabled, we should be able to manage user auths 125 126 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 127 @Override 128 public Void run() throws Exception { 129 try (Connection conn = ConnectionFactory.createConnection(conf)) { 130 VisibilityClient.setAuths(conn, new String[] { SECRET, CONFIDENTIAL }, 131 USER_RW.getShortName()); 132 } catch (Throwable t) { 133 fail("Should not have failed"); 134 } 135 return null; 136 } 137 }); 138 139 PrivilegedExceptionAction<List<String>> getAuths = 140 new PrivilegedExceptionAction<List<String>>() { 141 @Override 142 public List<String> run() throws Exception { 143 GetAuthsResponse authsResponse = null; 144 try (Connection conn = ConnectionFactory.createConnection(conf)) { 145 authsResponse = VisibilityClient.getAuths(conn, USER_RW.getShortName()); 146 } catch (Throwable t) { 147 fail("Should not have failed"); 148 } 149 List<String> authsList = new ArrayList<>(authsResponse.getAuthList().size()); 150 for (ByteString authBS : authsResponse.getAuthList()) { 151 authsList.add(Bytes.toString(authBS.toByteArray())); 152 } 153 return authsList; 154 } 155 }; 156 157 List<String> authsList = SUPERUSER.runAs(getAuths); 158 assertEquals(2, authsList.size()); 159 assertTrue(authsList.contains(SECRET)); 160 assertTrue(authsList.contains(CONFIDENTIAL)); 161 162 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 163 @Override 164 public Void run() throws Exception { 165 try (Connection conn = ConnectionFactory.createConnection(conf)) { 166 VisibilityClient.clearAuths(conn, new String[] { SECRET }, USER_RW.getShortName()); 167 } catch (Throwable t) { 168 fail("Should not have failed"); 169 } 170 return null; 171 } 172 }); 173 174 authsList = SUPERUSER.runAs(getAuths); 175 assertEquals(1, authsList.size()); 176 assertTrue(authsList.contains(CONFIDENTIAL)); 177 178 SUPERUSER.runAs(new PrivilegedExceptionAction<Void>() { 179 @Override 180 public Void run() throws Exception { 181 try (Connection conn = ConnectionFactory.createConnection(conf)) { 182 VisibilityClient.clearAuths(conn, new String[] { CONFIDENTIAL }, USER_RW.getShortName()); 183 } catch (Throwable t) { 184 fail("Should not have failed"); 185 } 186 return null; 187 } 188 }); 189 190 authsList = SUPERUSER.runAs(getAuths); 191 assertEquals(0, authsList.size()); 192 } 193 194 @Test 195 public void testPassiveVisibility() throws Exception { 196 // No values should be filtered regardless of authorization if we are passive 197 try (Table t = createTableAndWriteDataWithLabels(TableName.valueOf(TEST_NAME.getMethodName()), 198 SECRET, PRIVATE, SECRET + "|" + CONFIDENTIAL, PRIVATE + "|" + CONFIDENTIAL)) { 199 Scan s = new Scan(); 200 s.setAuthorizations(new Authorizations()); 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)); 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)); 213 try (ResultScanner scanner = t.getScanner(s)) { 214 Result[] next = scanner.next(10); 215 assertEquals(4, next.length); 216 } 217 s = new Scan(); 218 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL, PRIVATE)); 219 try (ResultScanner scanner = t.getScanner(s)) { 220 Result[] next = scanner.next(10); 221 assertEquals(4, next.length); 222 } 223 } 224 } 225 226 static Table createTableAndWriteDataWithLabels(TableName tableName, String... labelExps) 227 throws Exception { 228 List<Put> puts = new ArrayList<>(labelExps.length + 1); 229 for (int i = 0; i < labelExps.length; i++) { 230 Put put = new Put(Bytes.toBytes("row" + (i + 1))); 231 put.addColumn(TEST_FAMILY, TEST_QUALIFIER, HConstants.LATEST_TIMESTAMP, ZERO); 232 put.setCellVisibility(new CellVisibility(labelExps[i])); 233 puts.add(put); 234 } 235 Table table = TEST_UTIL.createTable(tableName, TEST_FAMILY); 236 table.put(puts); 237 return table; 238 } 239}