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.rsgroup; 019 020import static org.apache.hadoop.hbase.AuthUtil.toGroupEntry; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertTrue; 023import static org.junit.Assert.fail; 024 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.HBaseTestingUtility; 028import org.apache.hadoop.hbase.HConstants; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.TableNotFoundException; 031import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 032import org.apache.hadoop.hbase.client.Connection; 033import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 034import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 035import org.apache.hadoop.hbase.security.User; 036import org.apache.hadoop.hbase.security.access.AccessControlClient; 037import org.apache.hadoop.hbase.security.access.AccessControlLists; 038import org.apache.hadoop.hbase.security.access.Permission; 039import org.apache.hadoop.hbase.security.access.SecureTestUtil; 040import org.apache.hadoop.hbase.security.access.TableAuthManager; 041import org.apache.hadoop.hbase.testclassification.MediumTests; 042import org.apache.hadoop.hbase.testclassification.SecurityTests; 043import org.apache.hadoop.hbase.util.Bytes; 044import org.junit.AfterClass; 045import org.junit.BeforeClass; 046import org.junit.ClassRule; 047import org.junit.Test; 048import org.junit.experimental.categories.Category; 049import org.slf4j.Logger; 050import org.slf4j.LoggerFactory; 051 052/** 053 * Performs authorization checks for rsgroup operations, according to different 054 * levels of authorized users. 055 */ 056@Category({SecurityTests.class, MediumTests.class}) 057public class TestRSGroupsWithACL extends SecureTestUtil{ 058 059 @ClassRule 060 public static final HBaseClassTestRule CLASS_RULE = 061 HBaseClassTestRule.forClass(TestRSGroupsWithACL.class); 062 063 private static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsWithACL.class); 064 private static TableName TEST_TABLE = TableName.valueOf("testtable1"); 065 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 066 private static Configuration conf; 067 068 private static Connection systemUserConnection; 069 // user with all permissions 070 private static User SUPERUSER; 071 // user granted with all global permission 072 private static User USER_ADMIN; 073 // user with rw permissions on column family. 074 private static User USER_RW; 075 // user with read-only permissions 076 private static User USER_RO; 077 // user is table owner. will have all permissions on table 078 private static User USER_OWNER; 079 // user with create table permissions alone 080 private static User USER_CREATE; 081 // user with no permissions 082 private static User USER_NONE; 083 084 private static final String GROUP_ADMIN = "group_admin"; 085 private static final String GROUP_CREATE = "group_create"; 086 private static final String GROUP_READ = "group_read"; 087 private static final String GROUP_WRITE = "group_write"; 088 089 private static User USER_GROUP_ADMIN; 090 private static User USER_GROUP_CREATE; 091 private static User USER_GROUP_READ; 092 private static User USER_GROUP_WRITE; 093 094 private static byte[] TEST_FAMILY = Bytes.toBytes("f1"); 095 096 private static RSGroupAdminEndpoint rsGroupAdminEndpoint; 097 098 @BeforeClass 099 public static void setupBeforeClass() throws Exception { 100 // setup configuration 101 conf = TEST_UTIL.getConfiguration(); 102 conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, 103 RSGroupBasedLoadBalancer.class.getName()); 104 // Enable security 105 enableSecurity(conf); 106 // Verify enableSecurity sets up what we require 107 verifyConfiguration(conf); 108 // Enable rsgroup 109 configureRSGroupAdminEndpoint(conf); 110 111 TEST_UTIL.startMiniCluster(); 112 rsGroupAdminEndpoint = (RSGroupAdminEndpoint) TEST_UTIL.getMiniHBaseCluster().getMaster(). 113 getMasterCoprocessorHost().findCoprocessor(RSGroupAdminEndpoint.class.getName()); 114 // Wait for the ACL table to become available 115 TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME); 116 117 // create a set of test users 118 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 119 USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]); 120 USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]); 121 USER_RO = User.createUserForTesting(conf, "rouser", new String[0]); 122 USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]); 123 USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]); 124 USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]); 125 126 USER_GROUP_ADMIN = 127 User.createUserForTesting(conf, "user_group_admin", new String[] { GROUP_ADMIN }); 128 USER_GROUP_CREATE = 129 User.createUserForTesting(conf, "user_group_create", new String[] { GROUP_CREATE }); 130 USER_GROUP_READ = 131 User.createUserForTesting(conf, "user_group_read", new String[] { GROUP_READ }); 132 USER_GROUP_WRITE = 133 User.createUserForTesting(conf, "user_group_write", new String[] { GROUP_WRITE }); 134 135 systemUserConnection = TEST_UTIL.getConnection(); 136 setUpTableAndUserPermissions(); 137 } 138 139 private static void setUpTableAndUserPermissions() throws Exception { 140 TableDescriptorBuilder tableBuilder = TableDescriptorBuilder.newBuilder(TEST_TABLE); 141 ColumnFamilyDescriptorBuilder cfd = ColumnFamilyDescriptorBuilder.newBuilder(TEST_FAMILY); 142 cfd.setMaxVersions(100); 143 tableBuilder.setColumnFamily(cfd.build()); 144 tableBuilder.setValue(TableDescriptorBuilder.OWNER, USER_OWNER.getShortName()); 145 createTable(TEST_UTIL, tableBuilder.build(), 146 new byte[][] { Bytes.toBytes("s") }); 147 148 // Set up initial grants 149 grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(), 150 Permission.Action.ADMIN, 151 Permission.Action.CREATE, 152 Permission.Action.READ, 153 Permission.Action.WRITE); 154 155 grantOnTable(TEST_UTIL, USER_RW.getShortName(), 156 TEST_TABLE, TEST_FAMILY, null, 157 Permission.Action.READ, 158 Permission.Action.WRITE); 159 160 // USER_CREATE is USER_RW plus CREATE permissions 161 grantOnTable(TEST_UTIL, USER_CREATE.getShortName(), 162 TEST_TABLE, null, null, 163 Permission.Action.CREATE, 164 Permission.Action.READ, 165 Permission.Action.WRITE); 166 167 grantOnTable(TEST_UTIL, USER_RO.getShortName(), 168 TEST_TABLE, TEST_FAMILY, null, 169 Permission.Action.READ); 170 171 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN); 172 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE); 173 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ); 174 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE); 175 176 assertEquals(4, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size()); 177 try { 178 assertEquals(4, AccessControlClient.getUserPermissions(systemUserConnection, 179 TEST_TABLE.toString()).size()); 180 } catch (Throwable e) { 181 LOG.error("error during call of AccessControlClient.getUserPermissions. ", e); 182 fail("error during call of AccessControlClient.getUserPermissions."); 183 } 184 } 185 186 private static void cleanUp() throws Exception { 187 // Clean the _acl_ table 188 try { 189 deleteTable(TEST_UTIL, TEST_TABLE); 190 } catch (TableNotFoundException ex) { 191 // Test deleted the table, no problem 192 LOG.info("Test deleted table " + TEST_TABLE); 193 } 194 // Verify all table/namespace permissions are erased 195 assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size()); 196 assertEquals(0, AccessControlLists.getNamespacePermissions(conf, 197 TEST_TABLE.getNamespaceAsString()).size()); 198 } 199 200 @AfterClass 201 public static void tearDownAfterClass() throws Exception { 202 cleanUp(); 203 TEST_UTIL.shutdownMiniCluster(); 204 int total = TableAuthManager.getTotalRefCount(); 205 assertTrue("Unexpected reference count: " + total, total == 0); 206 } 207 208 private static void configureRSGroupAdminEndpoint(Configuration conf) { 209 String currentCoprocessors = conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY); 210 String coprocessors = RSGroupAdminEndpoint.class.getName(); 211 if (currentCoprocessors != null) { 212 coprocessors += "," + currentCoprocessors; 213 } 214 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, coprocessors); 215 conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, 216 RSGroupBasedLoadBalancer.class.getName()); 217 } 218 219 @Test 220 public void testGetRSGroupInfo() throws Exception { 221 AccessTestAction action = () -> { 222 rsGroupAdminEndpoint.checkPermission("getRSGroupInfo"); 223 return null; 224 }; 225 226 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 227 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 228 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 229 } 230 231 @Test 232 public void testGetRSGroupInfoOfTable() throws Exception { 233 AccessTestAction action = () -> { 234 rsGroupAdminEndpoint.checkPermission("getRSGroupInfoOfTable"); 235 return null; 236 }; 237 238 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 239 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 240 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 241 } 242 243 @Test 244 public void testMoveServers() throws Exception { 245 AccessTestAction action = () -> { 246 rsGroupAdminEndpoint.checkPermission("moveServers"); 247 return null; 248 }; 249 250 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 251 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 252 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 253 } 254 255 @Test 256 public void testMoveTables() throws Exception { 257 AccessTestAction action = () -> { 258 rsGroupAdminEndpoint.checkPermission("moveTables"); 259 return null; 260 }; 261 262 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 263 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 264 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 265 } 266 267 @Test 268 public void testAddRSGroup() throws Exception { 269 AccessTestAction action = () -> { 270 rsGroupAdminEndpoint.checkPermission("addRSGroup"); 271 return null; 272 }; 273 274 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 275 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 276 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 277 } 278 279 @Test 280 public void testRemoveRSGroup() throws Exception { 281 AccessTestAction action = () -> { 282 rsGroupAdminEndpoint.checkPermission("removeRSGroup"); 283 return null; 284 }; 285 286 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 287 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 288 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 289 } 290 291 @Test 292 public void testBalanceRSGroup() throws Exception { 293 AccessTestAction action = () -> { 294 rsGroupAdminEndpoint.checkPermission("balanceRSGroup"); 295 return null; 296 }; 297 298 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 299 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 300 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 301 } 302 303 @Test 304 public void testListRSGroup() throws Exception { 305 AccessTestAction action = () -> { 306 rsGroupAdminEndpoint.checkPermission("listRSGroup"); 307 return null; 308 }; 309 310 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 311 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 312 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 313 } 314 315 @Test 316 public void testGetRSGroupInfoOfServer() throws Exception { 317 AccessTestAction action = () -> { 318 rsGroupAdminEndpoint.checkPermission("getRSGroupInfoOfServer"); 319 return null; 320 }; 321 322 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 323 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 324 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 325 } 326 327 @Test 328 public void testMoveServersAndTables() throws Exception { 329 AccessTestAction action = () -> { 330 rsGroupAdminEndpoint.checkPermission("moveServersAndTables"); 331 return null; 332 }; 333 334 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 335 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 336 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 337 } 338}