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