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