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; 023 024import java.io.IOException; 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.client.Connection; 032import org.apache.hadoop.hbase.client.ConnectionFactory; 033import org.apache.hadoop.hbase.security.User; 034import org.apache.hadoop.hbase.testclassification.MediumTests; 035import org.apache.hadoop.hbase.testclassification.SecurityTests; 036import org.apache.hadoop.hbase.util.Bytes; 037import org.junit.AfterClass; 038import org.junit.BeforeClass; 039import org.junit.ClassRule; 040import org.junit.Rule; 041import org.junit.Test; 042import org.junit.experimental.categories.Category; 043import org.junit.rules.TestName; 044 045import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; 046 047import org.apache.hadoop.hbase.shaded.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse; 048import org.apache.hadoop.hbase.shaded.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse; 049 050@Category({ SecurityTests.class, MediumTests.class }) 051public class TestVisibilityLabelsOpWithDifferentUsersNoACL { 052 053 @ClassRule 054 public static final HBaseClassTestRule CLASS_RULE = 055 HBaseClassTestRule.forClass(TestVisibilityLabelsOpWithDifferentUsersNoACL.class); 056 057 private static final String PRIVATE = "private"; 058 private static final String CONFIDENTIAL = "confidential"; 059 private static final String SECRET = "secret"; 060 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 061 private static Configuration conf; 062 063 @Rule 064 public final TestName TEST_NAME = new TestName(); 065 private static User SUPERUSER; 066 private static User NORMAL_USER; 067 private static User NORMAL_USER1; 068 069 @BeforeClass 070 public static void setupBeforeClass() throws Exception { 071 // setup configuration 072 conf = TEST_UTIL.getConfiguration(); 073 VisibilityTestUtil.enableVisiblityLabels(conf); 074 String currentUser = User.getCurrent().getName(); 075 conf.set("hbase.superuser", "admin," + currentUser); 076 TEST_UTIL.startMiniCluster(2); 077 078 // Wait for the labels table to become available 079 TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000); 080 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 081 NORMAL_USER = User.createUserForTesting(conf, "user1", new String[] {}); 082 NORMAL_USER1 = User.createUserForTesting(conf, "user2", new String[] {}); 083 addLabels(); 084 } 085 086 @AfterClass 087 public static void tearDownAfterClass() throws Exception { 088 TEST_UTIL.shutdownMiniCluster(); 089 } 090 091 @Test 092 public void testLabelsTableOpsWithDifferentUsers() throws Throwable { 093 PrivilegedExceptionAction<VisibilityLabelsResponse> action = 094 new PrivilegedExceptionAction<VisibilityLabelsResponse>() { 095 @Override 096 public VisibilityLabelsResponse run() throws Exception { 097 try (Connection conn = ConnectionFactory.createConnection(conf)) { 098 return VisibilityClient.setAuths(conn, new String[] { CONFIDENTIAL, PRIVATE }, "user1"); 099 } catch (Throwable e) { 100 } 101 return null; 102 } 103 }; 104 VisibilityLabelsResponse response = SUPERUSER.runAs(action); 105 assertTrue(response.getResult(0).getException().getValue().isEmpty()); 106 assertTrue(response.getResult(1).getException().getValue().isEmpty()); 107 108 // Ideally this should not be allowed. this operation should fail or do nothing. 109 action = new PrivilegedExceptionAction<VisibilityLabelsResponse>() { 110 @Override 111 public VisibilityLabelsResponse run() throws Exception { 112 try (Connection conn = ConnectionFactory.createConnection(conf)) { 113 return VisibilityClient.setAuths(conn, new String[] { CONFIDENTIAL, PRIVATE }, "user3"); 114 } catch (Throwable e) { 115 } 116 return null; 117 } 118 }; 119 response = NORMAL_USER1.runAs(action); 120 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", 121 response.getResult(0).getException().getName()); 122 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", 123 response.getResult(1).getException().getName()); 124 125 PrivilegedExceptionAction<GetAuthsResponse> action1 = 126 new PrivilegedExceptionAction<GetAuthsResponse>() { 127 @Override 128 public GetAuthsResponse run() throws Exception { 129 try (Connection conn = ConnectionFactory.createConnection(conf)) { 130 return VisibilityClient.getAuths(conn, "user1"); 131 } catch (Throwable e) { 132 } 133 return null; 134 } 135 }; 136 GetAuthsResponse authsResponse = NORMAL_USER.runAs(action1); 137 assertTrue(authsResponse.getAuthList().isEmpty()); 138 authsResponse = NORMAL_USER1.runAs(action1); 139 assertTrue(authsResponse.getAuthList().isEmpty()); 140 authsResponse = SUPERUSER.runAs(action1); 141 List<String> authsList = new ArrayList<>(authsResponse.getAuthList().size()); 142 for (ByteString authBS : authsResponse.getAuthList()) { 143 authsList.add(Bytes.toString(authBS.toByteArray())); 144 } 145 assertEquals(2, authsList.size()); 146 assertTrue(authsList.contains(CONFIDENTIAL)); 147 assertTrue(authsList.contains(PRIVATE)); 148 149 PrivilegedExceptionAction<VisibilityLabelsResponse> action2 = 150 new PrivilegedExceptionAction<VisibilityLabelsResponse>() { 151 @Override 152 public VisibilityLabelsResponse run() throws Exception { 153 try (Connection conn = ConnectionFactory.createConnection(conf)) { 154 return VisibilityClient.clearAuths(conn, new String[] { CONFIDENTIAL, PRIVATE }, 155 "user1"); 156 } catch (Throwable e) { 157 } 158 return null; 159 } 160 }; 161 response = NORMAL_USER1.runAs(action2); 162 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", 163 response.getResult(0).getException().getName()); 164 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", 165 response.getResult(1).getException().getName()); 166 response = SUPERUSER.runAs(action2); 167 assertTrue(response.getResult(0).getException().getValue().isEmpty()); 168 assertTrue(response.getResult(1).getException().getValue().isEmpty()); 169 authsResponse = SUPERUSER.runAs(action1); 170 assertTrue(authsResponse.getAuthList().isEmpty()); 171 } 172 173 private static void addLabels() throws Exception { 174 PrivilegedExceptionAction<VisibilityLabelsResponse> action = 175 new PrivilegedExceptionAction<VisibilityLabelsResponse>() { 176 @Override 177 public VisibilityLabelsResponse run() throws Exception { 178 String[] labels = { SECRET, CONFIDENTIAL, PRIVATE }; 179 try (Connection conn = ConnectionFactory.createConnection(conf)) { 180 VisibilityClient.addLabels(conn, labels); 181 } catch (Throwable t) { 182 throw new IOException(t); 183 } 184 return null; 185 } 186 }; 187 SUPERUSER.runAs(action); 188 } 189}